我对大多数OOP理论都有很好的理解,但最让我困惑的是虚拟析构函数。

我以为析构函数总是被调用,不管是什么,也不管是链中的每个对象。

你打算什么时候让它们虚拟化?为什么?


当前回答

我认为这个问题的核心是关于虚拟方法和多态性,而不是具体的析构函数。下面是一个更清晰的例子:

class A
{
public:
    A() {}
    virtual void foo()
    {
        cout << "This is A." << endl;
    }
};

class B : public A
{
public:
    B() {}
    void foo()
    {
        cout << "This is B." << endl;
    }
};

int main(int argc, char* argv[])
{
    A *a = new B();
    a->foo();
    if(a != NULL)
    delete a;
    return 0;
}

将打印出:

This is B.

如果没有虚拟,它将打印出:

This is A.

现在您应该了解何时使用虚拟析构函数。

其他回答

我喜欢思考接口和接口的实现。在C++中,speak接口是纯虚拟类。析构函数是接口的一部分,需要实现。因此析构函数应该是纯虚拟的。构造函数呢?构造函数实际上不是接口的一部分,因为对象总是显式实例化的。

如果使用shared_ptr(仅shared_ptl,而不是unique_ptr),则不必将基类析构函数设为虚拟:

#include <iostream>
#include <memory>

using namespace std;

class Base
{
public:
    Base(){
        cout << "Base Constructor Called\n";
    }
    ~Base(){ // not virtual
        cout << "Base Destructor called\n";
    }
};

class Derived: public Base
{
public:
    Derived(){
        cout << "Derived constructor called\n";
    }
    ~Derived(){
        cout << "Derived destructor called\n";
    }
};

int main()
{
    shared_ptr<Base> b(new Derived());
}

输出:

Base Constructor Called
Derived constructor called
Derived destructor called
Base Destructor called

只要类是多态的,就将析构函数设为虚拟。

当您需要从基类调用派生类析构函数时。您需要在基类中声明虚拟基类析构函数。

我认为这个问题的核心是关于虚拟方法和多态性,而不是具体的析构函数。下面是一个更清晰的例子:

class A
{
public:
    A() {}
    virtual void foo()
    {
        cout << "This is A." << endl;
    }
};

class B : public A
{
public:
    B() {}
    void foo()
    {
        cout << "This is B." << endl;
    }
};

int main(int argc, char* argv[])
{
    A *a = new B();
    a->foo();
    if(a != NULL)
    delete a;
    return 0;
}

将打印出:

This is B.

如果没有虚拟,它将打印出:

This is A.

现在您应该了解何时使用虚拟析构函数。