关于继承的说明

时间:2013-05-03 21:57:06

标签: pointers inheritance constructor destructor derived-class

我有两个班,而B派生A

我创建了一个指向A的指针,名为a2。请查看我的main功能。

这条线做什么?

a2 = new B();

为什么当我删除a2时,只激活了A的析构函数?

#include <iostream>
using namespace std;

class A {
    int num;
  public:
    A() { cout << "constructor of A\n"; }
    void set_num(int new_num) { cout << "set_num of A" << endl; num = new_num; }
    void print() { cout << "print of A: ";  cout << num << endl; }
    ~A() { cout << "destructor of A\n"; }
};

class B: public A {
    int num;
  public:
    B() { cout << "constructor of B\n"; }
    void set_num(int new_num) { cout << "set_num of B" << endl; num = new_num; }
    void print() { cout << "print of B: ";  cout << num << endl; }
    ~B() { cout << "destructor of B\n"; }
};

void main() {
    A *a2;
    a2 = new B();
    delete a2;
}

这是输出:

constructor of A
constructor of B
destructor of A

每个帮助表示赞赏!

3 个答案:

答案 0 :(得分:1)

首先让你的析构函数虚拟化......

虚拟~A()...... 虚〜B()......

看这里:When to use virtual destructors?

答案 1 :(得分:1)

如果要通过指向基础子对象的指针删除对象,则基类的析构函数必须虚拟

class A
{
public:
    virtual ~A() { /* ... */ }
    // ...
};

(这会自动使所有派生类析构函数都是虚拟的,所以你不必拼写它。)

原因是C ++ 11标准中的第5.3.5 / 3条:

  

如果要删除的对象的静态类型与其不同   动态类型,静态类型应该是要删除的对象的动态类型的基类   静态类型应具有虚拟析构函数或行为未定义。

我确信你可以想象为什么虚拟析构函数是,但是对于一个简单的例子,想象指针到基础(就像你的a2)甚至不需要在数字上与指向acutal对象的指针 - 但是你需要确切的指针来释放内存。很明显,在找出正确的地址的过程中需要一些魔力。虚拟析构函数融入了这种魔力。

答案 2 :(得分:1)

所以这里最简单和最方便的解决方案是使用虚拟析构函数,但是让我展示另一个解决方案:帮助编译器。类型推断在这里很有用 - 如果你声明对象是作为特定类型,您将获得预期的行为:

int main()
{
    B *a2;
    a2 = new B();
    delete a2;
}

输出

constructor of A
constructor of B
destructor of B
destructor of A

此外,main()应该返回int,而不是void