GNU 컴파일러 경고“클래스에는 가상 기능이 있지만 비가가방 소멸 자”

StackOverflow https://stackoverflow.com/questions/127426

  •  02-07-2019
  •  | 
  •  

문제

C ++에서 인터페이스를 정의했습니다. 즉, 순수한 가상 함수 만 포함 된 클래스입니다.

인터페이스의 사용자를 명시 적으로 금지하고 인터페이스에 대한 포인터를 통해 객체를 삭제하려면 인터페이스에 대한 보호 및 비 약독 파괴자를 다음과 같은 것입니다.

class ITest{
public:
    virtual void doSomething() = 0;

protected:
    ~ITest(){}
};

void someFunction(ITest * test){
    test->doSomething(); // ok
    // deleting object is not allowed
    // delete test; 
}

GNU 컴파일러는 다음과 같은 경고를합니다.

클래스 'Itest'에는 가상 함수가 있지만 비 초가의 소멸자

파괴자가 보호되면 가상이거나 비 사건이있는 데있어 차이점은 무엇입니까?

이 경고가 안전하게 무시하거나 침묵 할 수 있다고 생각하십니까?

도움이 되었습니까?

해결책

컴파일러의 버그입니다. 최근 버전의 컴파일러 에서이 경고는 던져지지 않습니다 (적어도 4.3에서는 그렇지 않습니다). 파괴자를 보호하고 비 사건이없는 경우에는 합법적입니다.

보다 여기 주제에 관한 Herb Sutter의 훌륭한 기사. 기사에서 :

가이드 라인 #4 : 기본 클래스 소멸자는 공개 및 가상이거나 보호받지 않고 비판적이어야합니다.

다른 팁

이 답변에 대한 의견 중 일부는 내가 준 이전 답변과 관련이 있습니다.

보호 된 파괴자는 삭제를 통한 것이 아니라 기본 클래스에서만 호출 될 수 있음을 의미합니다. 즉, Itest*를 직접 삭제할 수 없으며 파생 클래스 만 할 수 있습니다. 파생 클래스는 가상 파괴자를 원할 수 있습니다. 코드에는 아무런 문제가 없습니다.

그러나 GCC에서 경고를 현지에서 비활성화 할 수없고 이미 VTABLE이 있으므로 어쨌든 소멸자를 가상으로 만드는 것을 고려할 수 있습니다. 클래스마다 4 바이트 (클래스 인스턴스 당), 최대의 비용이 듭니다. 파생 클래스 A 가상 DTOR를 제공했을 수도 있으므로 비용이 많이 들지 않을 수 있습니다.

이 작업을 고소하면 계속해서 통과하십시오. -Wno-non-virtual-dtor GCC에. 이 경고는 기본적으로 켜지지 않은 것 같습니다. -Wall 또는 -Weffc++. 그러나 대부분의 상황에서 이것은 버그가 될 것이기 때문에 유용한 경고라고 생각합니다.

It's an interface class, so it's reasonable you should not delete objects implementing that interface via that interface. A common case of that is an interface for objects created by a factory which should be returned to the factory. (Having objects contain a pointer to their factory might be quite expensive).

I'd agree with the observation that GCC is whining. Instead, it should simply warn when you delete an ITest*. That's where the real danger lies.

My personal view is that you'd doing the correct thing and the compiler is broken. I'd disable the warning (locally in the file which defines the interface) if possible,

I find that I use this pattern (small 'p') quite a lot. In fact I find that it's more common for my interfaces to have protected dtors than it is for them to have public ones. However I don't think it's actually that common an idiom (it doesn't get spoken about that much) and I guess back when the warning was added to GCC it was appropriate to try and enforce the older 'dtor must be virtual if you have virtual functions' rule. Personally I updated that rule to 'dtor must be virtual if you have virtual functions and wish users to be able to delete instances of the interface through the interface else the dtor should be protected and non virtual' ages ago ;)

If the destructor is virtual it makes sure that the base class destructor is also called fore doing the cleanup, otherwise some leaks can result from that code. So you should make sure that the program has no such warnings (prefferably no warnings at all).

If you had code in one of ITest's methods that tried to delete itself (a bad idea, but legal), the derived class's destructor wouldn't be called. You should still make your destructor virtual, even if you never intend to delete a derived instance via a base-class pointer.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top