#include
class CPerson {
public:
CPerson() {
ShowSpeak(0);
}
virtual ~CPerson() {
ShowSpeak(1);
}
virtual void ShowSpeak(int i) {
if(0 == i)
printf("%s::ShowSpeak()\r\n", GetClassName());
else
printf("~%s::ShowSpeak()\r\n", GetClassName());
}
virtual char* GetClassName() {
return "CPerson";
}
};
class CChinese : public CPerson {
public:
CChinese() {
ShowSpeak(0);
}
virtual ~CChinese() {
ShowSpeak(1);
}
virtual char* GetClassName() {
return "CChinese";
}
};
int main() {
CPerson *pPerson = new CChinese();
pPerson->ShowSpeak(0);
delete pPerson;
}
执行上面的程序,输出结果为:
CPerson::ShowSpeak()
CChinese::ShowSpeak()
CChinese::ShowSpeak()
~CChinese::ShowSpeak()
~CPerson::ShowSpeak()
从上面的输出结果中可以看到,虽然在CPerson的构造和析构函数中,调用了ShowSpeak虚函数,但实际的输出结果却没有调用CChinese::ShowSpeak()
原因是在任何一个类的析构和构造函数中,都会用本类的虚表指针替换当前this中的虚表指针,这样无论自己的构造和析构函数中怎么直接或间接调用其它函数,都能确保调用的是本类虚表的函数。
为什么要这么处理呢?
从析构来讲,是先析构子类,再析构父类;若在父类中通过虚表调用了子类的虚函数,由于子类已经被析构,这个调用就会出问题;
从构造来讲,是先构造父类,再是子类,子类都还没有构造完成,父类更加不能利用子类的虚表去调用了;
上面两个就是C++的语言规则,虚函数的正确使用是有明确限制的;
阅读(1009) | 评论(0) | 转发(0) |