多态不适用于析构函数的内部??
基类:
class B
{
public:
~B() { Dispose(); }
private:
virtual void Dispose() { printf("dispose in B.\n"); }
};
子类:
class D : public B
{
private:
virtual void Dispose() { printf("dispose in D.\n"); }
};
使用:
B * obj = new D;
delete obj;
析构的时候打印出"dispose in B.",为什么不能动态地决议到子类的Dispose呢(析构函数改成虚的也不行)?
问题点数:50、回复次数:11Top
1 楼FreeFice(庄鱼)回复于 2004-09-01 18:01:40 得分 5
你的~D()并不存在,因此调用的是B::~B(),而~B()只可能调用B::Dispose()。Top
2 楼WuYL7812(龙哥)回复于 2004-09-01 18:07:05 得分 10
把程序改成这样:
#include <stdio.h>
#include <stdlib.h>
class B
{
public:
virtual ~B() { Dispose(); }
public:
virtual void Dispose() { printf("dispose in B.\n"); }
};
class D : public B
{
public:
~D() { Dispose();}
virtual void Dispose() { printf("dispose in D.\n"); }
};
int main()
{
B * obj = new D;
delete obj;
system("pause");
return 0;
}
会先运行D的析构函数~D(),调用D::Dispose();,然后才调用B的析构函数,调用B::Dispose()
可以看出应该是D里新增加的内容先清除(比如申请的内存),然后清清除B的内容。
先运行的是子类的析构函数,然后基类的析构函数。构造时则相反。
当运行到B的析构函数时,D已析构了,D里先增加的内容已经无效了,只能是B的了。
你的例子运行的是D的默认析构函数。改成明式的就好理解了.Top
3 楼WuYL7812(龙哥)回复于 2004-09-01 18:10:45 得分 0
要是你所说的那样运行obj的析构函数时,Dispose()调用的是D::Dispose(),那么
D::Dispose()就调用了2次.我说在我改的那个例子上.
Top
4 楼WuYL7812(龙哥)回复于 2004-09-01 18:11:33 得分 0
这显然不是你希望的。
Top
5 楼langzi8818(┤天道酬勤┝爱老婆┦┷我是来学习滴┷)回复于 2004-09-02 00:31:53 得分 10
在B中的析够函数中,调用的函数就是析够函数所属的类拥有的函数~Top
6 楼nickshen()回复于 2004-09-02 08:50:56 得分 5
析构函数,构造函数等都是函数,需要调动才能执行,只不过这两个比较特殊,由编译器调动了,所以其函数名是严格规范的。
既然是这样,在一个有虚函数的类中,虚函数都是通过vtpr调用的,析构也是如此,如果在基类的析构中使用虚函数机制,如何在继承类中调用到继承类的析构呢,可以看一下effective c++
上面你那个object指针是b对象的,这是在编译器就定好的,程序运行的时候通过vtpr才会确定是d对象,这才是后期绑定Top
7 楼steedhorse(晨星)回复于 2004-09-02 08:54:32 得分 5
To:楼上
“析构函数,构造函数等都是函数”,但是一般的成员函数可以的。Top
8 楼plainsong(短歌)()回复于 2004-09-02 10:10:44 得分 15
标准文档中是有明确规定的(12.7.3),当在某一个类的构造和析构函数中调用(或间接调用)虚函数时,它将调用自己或基类的函数,而不会去调用衍生类的构造函数。原文如下:
……When a virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from a destructor, and gthe object to which the call applies is the object under construction or destruction the function called is the one defined in the constructor or destructor's own class or in one of its bases but no t function overriding it in a class derived from the constructor or destructor's class, or overriding it in one of the other base classes of the most derived object.……
这样作是有道理的。用楼主的代码作为例子,当~B被调用时,~D必然已经完成调用(根据C++严格的析构顺序),同样在B构造时,D的构造也一定没有开始,这时*this已经不是一个合法的D对象了,如果在这里调用D的任何非静态成员函数(可以通过类限定符强制实现),其行为都是“未定义”。这样在我们没有用类限定符而让编译器自己选择的话,它当然不会去选择这个“未定义”的行为——否则只要一个成员函数定义为虚的就不能在构造和析构中使用了。Top
9 楼plainsong(短歌)()回复于 2004-09-02 10:16:14 得分 0
这样并不能说,析构函数中多态不起作用:
class B
{
private:
virtual void DoDispose() { printf("dispose in B.\n"); }
public:
void Dispose(){DoDispose();}
virtual ~B() {}
};
class D : public B
{
private:
virtual void DoDispose() { printf("dispose in D.\n"); }
public:
~D(){Dispose();}
};
class E: public D
{
private:
virtual void DoDispose() { printf("dispose in E.\n"); }
};
int main()
{
E obj;
}
这时Dispose会调用D::DoDispose,但Dispose是B的函数,很明显这是多态的效果;但与在外部调用不同的是,在外部直接调用obj.Dispose时将调用E::DoDispose。Top
10 楼steedhorse(晨星)回复于 2004-09-02 13:27:26 得分 0
精彩。Top
11 楼scbeans(笨死)回复于 2004-09-02 13:49:49 得分 0
厉害!!
楼上的几位都很厉害!
多谢指教,我明白了!Top




