Nice programing

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

nicepro 2020. 12. 12. 12:29
반응형

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


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 바이트 (클래스 인스턴스 당 아님)입니다. 파생 클래스에 가상 dtor를 제공했을 수 있으므로 비용이 들지 않을 수 있습니다.


이것을 고집한다면 -Wno-non-virtual-dtorGCC로 넘어가십시오 . 이 경고는 기본적으로 켜지지 않는 것 같으므로 -Wall또는으로 활성화해야합니다 -Weffc++. 그러나 대부분의 상황에서 이것은 버그가 될 것이기 때문에 유용한 경고라고 생각합니다.


인터페이스 클래스이므로 해당 인터페이스를 통해 해당 인터페이스를 구현하는 객체를 삭제하지 않는 것이 합리적입니다. 일반적인 경우는 공장으로 반환되어야하는 공장에서 생성 된 객체에 대한 인터페이스입니다. (객체에 공장에 대한 포인터가 포함되어 있으면 비용이 많이들 수 있습니다.)

나는 GCC가 징징 대고 있다는 관찰에 동의합니다. 대신 ITest *를 삭제할 때 경고 만 표시됩니다. 그것이 진짜 위험이있는 곳입니다.


내 개인적인 견해는 올바른 일을하고 컴파일러가 고장났다는 것입니다. 가능한 경우 경고 (인터페이스를 정의하는 파일에서 로컬로)를 비활성화합니다.

나는이 패턴 (작은 'p')을 꽤 많이 사용한다는 것을 알았습니다. 사실 내 인터페이스가 공개 된 것보다 dtor를 보호하는 것이 더 일반적이라는 것을 알게되었습니다. 그러나 나는 그것이 실제로 그렇게 흔한 관용구라고 생각하지 않습니다 (그렇게 많이 언급되지 않습니다) 그리고 경고가 GCC에 추가되었을 때 이전의 'dtor는 가상이어야합니다. 가상 기능의 규칙이 있습니다. 개인적으로 나는 그 규칙을 '가상 기능이 있고 사용자가 인터페이스를 통해 인터페이스의 인스턴스를 삭제할 수 있기를 원하면 dtor가 가상이어야합니다.


소멸자가 가상이면 정리를 수행하기 전에 기본 클래스 소멸자가 호출되는지 확인합니다. 그렇지 않으면 해당 코드에서 일부 누출이 발생할 수 있습니다. 따라서 프로그램에 그러한 경고가 없는지 확인해야합니다 (일반적으로 경고가 전혀 없음).


ITest의 메서드 중 하나에 delete자신 을 시도하는 코드가있는 경우 (나쁜 생각이지만 합법적 임) 파생 클래스의 소멸자가 호출되지 않습니다. 기본 클래스 포인터를 통해 파생 인스턴스를 삭제하지 않더라도 소멸자를 가상으로 만들어야합니다.

참고 URL : https://stackoverflow.com/questions/127426/gnu-compiler-warning-class-has-virtual-functions-but-non-virtual-destructor

반응형