代码之家  ›  专栏  ›  技术社区  ›  sdg

C++类类的析构函数

c++
  •  22
  • sdg  · 技术社区  · 15 年前

    开始在现有的代码基础上使用pc lint(恐惧和恐惧)。

    它抱怨的一件事是:

     class IBatch
     {
     public:
        virtual void StartBatch() =0;
        virtual int CommitBatch() =0;
     };
    

    当另一个类从这个派生来像接口一样使用它时,

    base class 'IBatch' has no destructor
    

    所以,问题是:当你创建 界面 像上面这样的类,是否总是包含一个虚拟析构函数?为什么?(是样式错误还是编码错误?)

    编辑:应该说我不期望或不想要 用户 对于要销毁的IBatch,它们只是一个服务的使用者,通过这个接口到一些外部实现类(如果这会有区别的话)

    6 回复  |  直到 14 年前
        1
  •  28
  •   James McNellis    15 年前

    基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。

    (Herb Sutter, Guru of the Week #18: "Virtuality")

        2
  •  8
  •   stefanB    15 年前

    编码错误-如果通过指向基类的指针调用,派生类的析构函数将永远不会被调用。

    当你实施 IBatch 通过指向基类的指针(指向 I批量 你打电话给我 delete 在指向基类的指针上,可能会导致内存泄漏,因为派生类的析构函数永远不会被调用。

    基本规则是当一个类至少有一个 virtual 它需要的方法 事实上的 析构函数。

    class IBatch
    {
        public:
           virtual void f() = 0;
    };
    
    class A : public IBatch
    {
        public:
           void f() {}
           ~A() {}
    };
    
    IBatch * a = new A();
    a->f();    // calls A::f()
    delete a;  // calls IBatch::~IBatch() not A::~A()
    
        3
  •  7
  •   Billy ONeal IS4    14 年前

    如果存在虚拟函数,则需要有一个虚拟析构函数。总是。它只是一个接口类并不重要——它仍然需要虚拟析构函数。

    要么,要么它需要一个 protected 非虚拟析构函数。但是您不能使用接口指针删除对象。

        4
  •  4
  •   Alex Martelli    15 年前

    带有虚函数但没有虚析构函数的类是可疑的,而且很可能是错误的:请看一个好的、更精确的解释 here .

        5
  •  2
  •   Goz    15 年前

    所以,问题是:当你创建 像上面这样的接口类,do 您总是包括虚拟 析构函数?为什么?(是一种风格还是一种 编码错误?)

    这要看情况而定。如果您曾经调用过IBatch指针上的delete,它可能不会执行您所期望的操作。当然,如果您有类似于虚拟初始化/关闭或addref/releases的东西,那么它实际上不是一个问题。

        6
  •  0
  •   baris.aydinoz    15 年前

    编译器将默认析构函数设置为非虚拟的,这意味着指向虚拟基类的指针上的“delete”将成功,并导致内存泄漏。因此,这是一个实现缺陷,既不是样式,也不是编码错误。