2012-05-25 5 views
0

, 나는 다음과 같은 문제가 : 나는 아주 간단한 상속 방식이C++ : CRTP 소멸자? 프로젝트에

를 (I 상속하지 구성 필요) :

수준의 자료를

-> 클래스 DerivedA

-> 클래스 DerivedB

은 -를

A, B 및 C는 바에서 클래스를 유도 DerivedC> 그게 다야. 그래서 지금은 2 개 선택이 있습니다 virtuality와

공공 상속을

일부 최적화 이유 (내가 인라인을 많이 필요로) 나는 virtuality을 원하지 않는 내용은 virtuality

없이

개인 상속 ... 그리고 나는 개인적인 상속을 원하지 않는다. 나는 남아있는 유일한 옵션이 CRTP라고 생각한다. 하지만 기본 클래스는 300 가지 기능을 가지고 있으며 CRTP를 구현하면 정말 고통 스러울 것입니다.

그래서 나는 다음과 같은 솔루션이 유효한지 궁금 : 난 단지 기본 클래스의 소멸자에서 CRTP를 사용 TCRTP이 DerivedA, B 또는 C와 I는 공공 상속을 할 것

template<class TCRTP> class Base 
{ 
    ~Base() {delete static_cast<TCRTP*>(this);} 
} 

. 완벽하게 괜찮습니까, 아니면 문제가 있습니까?

대단히 감사합니다.

+6

필자는 필요없는 경우 일반 가상 상거래를 사용하지 않는 이유를 이해하지 못합니다. – Mat

+3

그건 의미가 없기 시작합니다. 참조를 삭제할 수 없으며'delete this'를 유용한 방식으로 말하지 않을 수 있습니다. 실제 문제에 대해 작고 대표적인 예를 게시 할 수 있습니까? –

+0

원래 코드에서 실수를했습니다. – Vincent

답변

8

소멸자가 잘못되었습니다. 클래스의 소멸자는 객체에 대한 메모리가 아니며 반드시 포함해야하지 않습니다 (delete).

가상 기능이없는 공용 상속에 대한 귀하의 반대는 무엇입니까? 누군가가 우연히 기본 포인터를 통해 파생 된 객체를 삭제하는 것을 방지하는 방법은 (적어도) 두 가지가 있습니다. 하나는 기본 소멸자를 만드는 것입니다 protected.

또 하나는 shared_ptr에 직접 파생 클래스의 동적 할당 인스턴스를 채우는 것입니다. 이것은 심지어 shared_ptr<Base> 될 수 있습니다 인수의 유형을 캡처하는 템플릿 생성자가

std::shared_ptr<Base> foo(new DerivedA(...)); 

shared_ptr 때문에, Base* 포인터는 shared_ptr와 관련된 Deleter가 기능에 DerivedA*로 변환하고, 따라서 제대로 삭제됩니다. 어느 누구도 shared_ptr에서 포인터를 추출하고 Base*으로 삭제하려고 시도하면 안됩니다.

물론 가상 함수가없는 경우 파생 클래스 간의 유일한 차이점은 생성자에서 설정 한 것일뿐입니다. 그렇지 않으면 shared_ptr에서 Base* 포인터를 내 보내야합니다.이 경우 먼저 shared_ptr<DerivedA>을 사용해야합니다.

+3

+1은'shared_ptr'에 대한 흥미로운 사실입니다. –

1

내부적으로 IUnknown::Release의 구현과 같은 코드를 사용할 수 있지만 결코 소멸자는 사용할 수 없습니다.Base 소멸자는 파생 된 개체가 소멸 된 후에 만 ​​실행되며 delete에 도달하면 파생 개체가 정의되지 않은 동작을 시도합니다. 나는 당신이 그 특별한 경우에 무한 재귀를 얻을 것이라고 확신합니다.