读书人

为啥说析构函数里面不要调虚函数

发布时间: 2013-11-21 23:38:25 作者: rapoo

为什么说析构函数里面不要调虚函数?
Effective C++里面说道"析构函数里面不要调虚函数",但是书里面举的例子是构造函数里面不要调虚函数,并没有举析构函数的例子啊。

这样做会有什么风险吗? 请举例提示! 谢谢
[解决办法]
在继承层次中,先析构派生类。
[解决办法]
先析构派生类,然后析构基类的时候,析构函数里面有个虚函数,虚函数表的地址是派生类的某个函数,这时候派生类都已经析构了。。
[解决办法]
基本上就像楼上说的,再基类中调用的虚函数不是子类的,而是基类本身的。在析构的时候,虚函数会变成类似non-virtual的效果。当然你知道了这结果,然后你故意把他当作non-virtual的版本去使用,理论上不会算错,但是virtual这个词会造成歧义性,对维护的人来说会带来困扰。参考代码如下:

class A{
public:
virtual void display()=0;

void f(){
display();//这里调用的是子类的没问题吧
}

virtual ~A(){
display();//但这里调用的是基类的,如果你实现了虚函数仍然可以运行,但会有歧义
//如果没有实现,直接就报错了
//这样不如直接用non-virtual函数
}
};

class B:public A{
public:
virtual void display(){
cout<<"B"<<endl;
}
};

int main(){
B *p=new B;
p->f();
delete p;
}

[解决办法]
在概念上,当基类的构造函数执行的时候,派生类尚未被构造,当基类的析构函数执行的时候,派生类已经析构完成
因此,在构造函数和析构函数中,虚函数的“虚”将不起作用,基类调用的虚函数就是基类的该函数,也正因为如此,纯虚函数不能在构造函数和析构函数中被调用
[解决办法]
引用:
Quote: 引用:

基本上就像楼上说的,再基类中调用的虚函数不是子类的,而是基类本身的。在析构的时候,虚函数会变成类似non-virtual的效果。当然你知道了这结果,然后你故意把他当作non-virtual的版本去使用,理论上不会算错,但是virtual这个词会造成歧义性,对维护的人来说会带来困扰。参考代码如下:
class A{
public:
virtual void display()=0;

void f(){
display();//这里调用的是子类的没问题吧
}

virtual ~A(){
display();//但这里调用的是基类的,如果你实现了虚函数仍然可以运行,但会有歧义
//如果没有实现,直接就报错了
//这样不如直接用non-virtual函数
}
};

class B:public A{
public:
virtual void display(){
cout<<"B"<<endl;
}
};

int main(){
B *p=new B;
p->f();
delete p;
}


你的这段代码根本编译不过的,GCC和VC都提示A::Display没有实现体。

我注释里解释了啊,纯虚函数可以实现也可以不实现。但你如果声明的是一个纯虚函数,并且没定义这个虚函数,肯定就是错的。
你改成这个就OK了:
virtual void display()=0{
cout<<"A"<<endl;
}

[解决办法]
引用:
Quote: 引用:

先析构派生类,然后析构基类的时候,析构函数里面有个虚函数,虚函数表的地址是派生类的某个函数,这时候派生类都已经析构了。。

你说的这个"析构函数里面有个虚函数,虚函数表的地址是派生类的某个函数",我觉得实际编码做不到。
基类如果有一个纯虚函数=0,那么在基类的析构函数里面根本就不能调它,因为没有函数的实现体。

你能举出一个代码的例子吗?


说错!对不起 析构函数里面有个虚函数,虚函数表的地址是派生类的某个函数 这句话是错的,这时候虚函数表的地址是基类的某个函数
[解决办法]
http://hi.baidu.com/marktian/item/e36fd1f78c4c834c932af285
关于这方面,这是我以前看到的一个解释得比较好的博客
[解决办法]
这种写法无法构成多态

读书人网 >C++

热点推荐