2017-01-19 59 views
-4

是否调用在基类的析构函数中有虚函数是一个很好的做法?而“是否在破坏时虚函数表的存在?,并呼吁建议在析构虚函数?什么时候在C++中破坏vtable?

+1

Vtables是与类相关的静态数据结构,而不是对象。 –

+0

发布一些代码,说明你在问什么。 –

+0

Vtable是多态类的静态对象。但是Vtable实际上是一个指针。如果我知道这个指针何时被删除,我会很高兴。 –

回答

2

我可以调用基类的析构函数虚函数?

从析构函数或构造函数调用虚函数是一种不好的做法。看到标准(重点煤矿):

12.7构造和析构
....
成员函数,包括虚拟功能(10.3),可建设或破坏(12.6.2)时被调用。 当构造或销毁类的非静态数据成员期间,构造函数或析构函数直接或间接调用虚函数时,包括 ,并且调用的对象是对象(称之为x )正在建设或销毁中,所调用的函数是构造函数或析构函数类中的最终覆盖函数 ,而不是覆盖更多派生类中的函数。如果虚拟 函数调用使用的显式类成员访问(5.2.5)和对象表达指的x或该对象的基类的子对象中的一个,但不是x或它的基类的子对象中的一个的完整 目的, 行为未定义

您可以在许多来源找到这个建议,其中包括斯科特迈尔斯
有效的C++:55层具体的方法来提高你的程序以及设计项目9:不要调用施工或破坏时虚函数。 )

或香草萨特的
C++编码标准:101条规则,准则和最佳实践49.避免调用虚函数的ns in constructors and destructors)。

2

是的,当调用析构函数时,对象将有一个指向其vtable的指针。

该标准明确表示可以在析构函数中调用虚函数,并说明会发生什么。有人认为,即使允许,这也是一个不好的做法,因为它本质上是脆弱的代码,导致显然无辜的变化带来惊喜。

如果您有从DerDerDer继承,从Base继承,所有的人都覆盖成员函数void member(),你是在Der析构函数,并调用member(),您呼叫Der::member(),不DerDer::member(),因为DerDer你的对象的一部分已经完成,已经消失。基类可无意中指数据在派生类,例如:

struct Base { 
    int *ip; 
    Base(int *ip): ip(ip) {} 
    virtual void useInt() { std::cout << *ip << std::endl; } 
    ~Base() { useInt(); } 
}; 
struct Der: Base { 
    int theInt; 
    Der(): Base(&theInt) {} 
    void useIntPointer() override { std::cout << theInt << std::endl; } 
}; 

Der类型的对象被删除,有“未定义的行为”:首先Der隐式析构函数被调用,则该显式析构函数BaseBase::~Base。此时Base::ip指的是已经销毁的Der的成员。

相关问题