내 코드에서 nullptr을 확인해야 할 필요가 있음을 알았습니다 (지정된 요구 사항에 따라 nullptr이 가능하지 않아도 됨).null 포인터를 피하고 다형성을 유지
그러나 다른 사람이 nullptr을 보낼 수도 있기 때문에 nullptr이 계속 발생할 수 있습니다. (불행히도 모든 사람이 읽기/쓰기를 할 수있는 것은 아닙니다.) 테스트 중에 런타임에 문제가 발생하지 않으면이 결함을 발견 할 수 없습니다. 높은 테스트 커버리지는 비싸다). 따라서 고객이보고 한 많은 출시 후 버그로 이어질 수 있습니다.
class data
{
virtual void foo() = 0;
};
class data_a : public data
{
public:
virtual void foo(){}
};
class data_b : public data
{
public:
virtual void foo(){}
};
void foo(const std::shared_ptr<data>& data)
{
if(data == nullptr) // good idea to check before use, performance and forgetting check might be a problem?
return;
data->foo();
}
보통 나는 값 유형을 사용하고 참조 및 복사를 전달합니다. 그러나, 어떤 경우에는 포인터 또는 참조가 필요한 다형성이 필요합니다.
그래서 다음과 같은 "컴파일 시간 다형성"을 사용하기 시작했습니다.
class data_a
{
public:
void foo(){}
private:
struct implementation;
std::shared_ptr<implementation> impl_; // pimpl-idiom, cheap shallow copy
};
class data_b
{
public:
void foo(){}
private:
struct implementation;
std::shared_ptr<implementation> impl_; // pimpl-idiom, cheap shallow copy
};
class data
{
public:
data(const data_a& x) : data_(x){} // implicit conversion
data(const data_b& x) : data_(x){} // implicit conversion
void foo()
{
boost::apply(foo_visitor(), data_);
}
private:
struct foo_visitor : public boost::static_visitor<void>
{
template<typename T>
void operator()(T& x){ x.foo(); }
};
boost::variant<data_a, data_b> data_;
}
void foo(const data& data)
{
data.foo();
}
실용적인 경우 다른 사람이이 방법을 사용하는 것이 좋습니다. 또는 나는 무엇인가 놓치고 있냐? 이 관행에 잠재적 인 문제점이 있습니까?
편집 : 사용하여 참조가
은 "문제는"당신이 (예를 들어, 객체를 반환) 참조의 소유권을 이동할 수 없습니다입니다.
data& create_data() { data_a temp; return temp; } // ouch... cannot return temp;
를 rvalue 참조의 문제 (다형성를 rvalue 참조와 함께 작동합니까?)
는 소유권을 공유 할 수 있다는된다. shared_ptr을 기반으로data&& create_data() { return std::move(my_data_); } // bye bye data
A "안전"포인터가 좋은 아이디어 같은 소리 않습니다,하지만, 난 여전히 비 nullness은 어쩌면, 컴파일시에 가능하지 적용됩니다 솔루션 싶습니다.
코드를 다시 편집해야합니다. 어떤 곳에서는 포인터와 참조를 섞고 있고, 포인터는 null 일 수 있고, 역 참조는'->'연산자를 사용합니다; 참조는 null이 될 수 없으며, 참조 해제는'.' 연산자를 사용합니다. –
흠 ... 문제가 보이지 않습니다. 그것이 어디 있는지 지적 해 주시겠습니까? – ronag
기타 작은 것들 : * 모든 * 생성자를 정의한 후에는 컴파일러가 기본 생성자를 생성하지 않고 (private으로 정의 할 필요가 없음) 기본 생성자에 필요하지 않은 하나의 생성자를 실제로 비활성화하려는 경우 - - 비공개로 선언하는 것이 좋지만 정의하지는 않습니다. 비공개 인 것은 컴파일시에 다른 클래스의 사용을 캐치 할 것이고, 링크를 정의하지 않으면 링크시 자신의 클래스 (또는 친구들)에서 사용을 캐치 할 것입니다. –