2009-07-13 2 views
39

기본 소멸자가 가상 ​​소멸자로 자동 생성 될 수 있습니까?기본 소멸자가 가상 ​​소멸자로 자동 생성 될 수 있습니까?

기본 클래스를 정의하지만 기본 소멸자가없는 경우 기본 가상 소멸자 이 자동으로 생성됩니까?

+0

그건 그렇고, 궁금해서, 기본 destrutor 무엇입니까? 거기에 더 많은 종류의 소멸자가 있습니까? – user88637

+4

@ yossi1981 : 클래스에 소멸자를 선언하지 않으면 컴파일러에서 삽입합니다. 비정상적인 경우에 대해 잘못 될 위험이 있으므로이 "기본 소멸자"는 "~ MyClass() {}"를 정의한 경우와 같습니다. –

+3

@onebyone : 정확하게 : public : ~ MyClass() {}'- 클래스 멤버는 기본적으로 private 임에도 불구하고. – MSalters

답변

37

아니요. 가상 메서드를 만드는 데 드는 비용이 있습니다. C++에는 사용하려는 명시 적으로 명시하지 않은 것에 대해 비용을 지불하지 않는 철학이 있습니다. 가상 소멸자가 자동으로 생성 되었다면 자동으로 가격을 지불했을 것입니다.

왜 비어있는 가상 소멸자를 정의하지 않는가?

+42

[C++ 11] (http://en.cppreference.com/w/cpp/language/member_functions#Special_member_functions)에서'virtual ~ Foo() = default;를 할 수 있습니다. 최근에 이것을 읽었습니다.) – CoryKramer

+1

클래스에 다른 가상 함수가 전혀 없으면 어떤 추가 비용이들 수 있습니까? 예를 들어 주시겠습니까? – Spencer

+0

@Spencer : 소멸자를 호출 할 때 객체의 vtable을 통해 런타임에 해석 될 d-tor 코드의 주소가 필요합니다. 비 가상 소멸자의 경우 코드의 주소는 컴파일 타임에 알려집니다. –

1

아니요. 가상으로 선언해야합니다.

8

Uri와 Michael이 맞습니다. 헤더를 최소한으로 인라인으로 정의하는 것은 완벽합니다.

class MyClass 
{ 
    // define basic destructor right here 
    virtual ~MyClass(){} 

    // but these functions can be defined in a different file 
    void FuncA(); 
    int FuncB(int etc); 
} 
+0

실제로이 링크를 연결하면 MyClass의 vtable에 대한 정의되지 않은 참조가 나타납니다. – keraba

+2

GCC를 사용하고 있고 FuncA 및 FuncB를 비 - 인라인으로 정의하지 않은 경우 "vtable에 대한 정의되지 않은 참조"오류 만 표시됩니다. 이는 GCC가 적절한 조치를 취하기 위해 필요한 모든 항목을 방출하지 못했기 때문입니다 연결. –

+0

나는 이것에 놀랐다. 왜 이것이 연결 문제를 일으키는가? 누군가 정교 할 수 있습니까? – Uri

9

아니요, 모든 소멸자는 기본적으로 가상이 아닙니다.

당신은 모든 기본 클래스 그 외에도

에 가상 소멸자를 정의해야합니다.

실제로

The C++ language standard is unusually clear on this topic. When you try to delete a derived class object through a base class pointer and the base class has a non-virtual destructor (as EnemyTarget does), the results are undefined

, 당신이 누군가가 결국 파생 클래스를 만들 수 있습니다이라고 생각하면 가상 소멸자를 가진 클래스를 정의하는 것이 좋습니다 보통이다 :

그의 책 "효과적인 C++"에서 스콧 마이어스를 인용 그것에서. 어쨌든 모든 클래스에는 가상 소멸자가 있습니다. 그렇습니다. 이와 관련된 비용이 있습니다.하지만 가상화를하지 않는 비용은 실행 시간 오버 헤드의 상당 부분을 차지합니다.

컴파일러가 적용하는 기본 비 가상에 의존하는 것이 아니라 절대적으로 원하는 경우에만 가상이 아닌 것으로 설정하는 것이 좋습니다. 당신은 동의하지 않을 수 있습니다 (요약) 그러나 나는 최근에 내가 몇년 동안 존재했던 클래스 중 하나에 std :: vector를 추가하는 레거시 코드에서 무서운 메모리 누수를 겪었습니다. 그 중 하나는 기본 클래스가 소멸자를 정의하지 않은 것으로 밝혀졌습니다 (기본 소멸자는 비어 있고 가상이 아닙니다!) 그리고 그 시점까지 메모리가 유출되기 전에 메모리가 할당되지 않았기 때문입니다. 많은 조사와 시간이 나중에 낭비되었습니다 ...

+1

상황을 올바르게 이해하면 코드가 변경되기 전에 이미 정의되지 않은 동작 (메모리 누수가 아님)이 있습니다. 기본 클래스 포인터를 통해 삭제되면 파생 객체가 파기되지 않고 기본 파괴됩니다 . 다른 데이터 멤버가 없으면 (파괴가 필요함) 동작을 정의하지 않습니다. 그래서 당신의 조사는 낭비되지 않았습니다 ... –

9

예, 가상 소멸자가있는 기본 클래스에서 상속을받습니다. 이 경우 이미 다형성 클래스 (예 : vtable)의 가격을 지불했습니다.

43

C++ 11에서는 사용할 수 있습니다

class MyClass 
{ 
    // create a virtual, default destructor 
    virtual ~MyClass() = default; 
}; 
+0

이것은''icpc''로 컴파일되지만''g ++ - 4.6.3''으로 컴파일되지 않고''error : ~virtual MyClass :: ~ MyClass() 클래스 본체에 가상을 기본값으로 설정할 수 없습니다. 그들은 당신이 이것을하기를 원하지 않는다고 아주 명백하게 보입니다. 이것이 작동하는''g ++''버전이 있습니까? – user14717

+1

@NickThompson, 나는 이것을 gcc 4.8.1과 4.9.0에 성공적으로 사용했다. [이것이 4.6에서 지원되는 것 같습니다] (https://gcc.gnu.org/gcc-4.6/cxx0x_status.html). '-std = C++ 0x'로 컴파일하고 있습니까? –

+0

나는이었다; 거기에서 무슨 일이 일어나고 있는지 확실하지 않습니다. – user14717

2

현재 열린이 권리입니다. 반면에 클래스에서 가상 메소드를 선언 한 후에는 가상 테이블의 존재 가격을 지불하고 있습니다. 실제로 클래스에 가상 메소드가 있지만 가상 소멸자가없는 경우 컴파일러에서 경고합니다. 이는 성가신 경고 대신 기본 가상 소멸자를 자동으로 생성 할 수있는 후보가 될 수 있습니다.

관련 문제