虚函数深入挖掘-构造函数与虚函数【1】
? ? 构造函数不能为虚函数,因为虚函数依赖虚函数表,构造函数尚未执行时,指向虚函数表的指针还不存在,因此显然构造函数无法成为虚函数。另外子类名字与父类不同,类的构造函数无法继承,更不能通过指针或引用去调用,因此跟虚函数也沾不上边。但是构造函数能否调用虚函数?按理说,构造函数没执行完,虚函数表都没有呢还。 ? ? 先来一个最基本的代码: ? ?? #include <stdio.h> class A { public: A(){} ~A(){} virtual void print(){printf("Basen");} }; class B:public A { public: B(){} ~B(){} void print(){printf("Bb");} }; class C:public A { public: C(){} ~C(){} void print(){printf("Cb");} }; int main() { A a; B b; C c; A *p=NULL; int choice; printf("Input choice="); scanf("%d",&choice); switch(choice) { case 1: p=&a; break; case 2: p=&b; break; case 3: p=&c; break; default: p=&a; } p->print(); getchar(); return 0; } ? ? 结果: ? ?? ? ? 在构造函数里调用虚函数: class A { public: A() { print(); } ~A(){} virtual void print(){printf("Basen");} }; class B:public A { public: B():A() { print(); } ~B(){} void print(){printf("Bb");} }; class C:public A { public: void print(){printf("Cb");} C() :A() { print(); } ~C(){} }; class A { public: A() { print(); } ~A(){} virtual void print(){printf("Basen");} }; class B:public A { public: B():A() { print(); } ~B(){} void print(){printf("Bb");} };? ? ? class C:public A? {? public:? void print(){printf("Cb");}? C() :A() {? print();? }? ~C(){}? };?int main() { A a; printf("n"); B b; printf("n"); C c; return 0; } 但是有几次只输出了Base,Base,Base。 参考资料: http://dev.yesky.com/441/2033941.shtml 这里给出的解释是说,构造函数需要调用基类的构造函数,然后再执行本身的构造部分,所以呢,当本身的那部分还没开始的时候,编译器只认为这是一个基类对象。于是,就会调用基类对应的函数了!面试的时候只想着按指针来找,结果杯具了。考官gg说,你回去跑跑看。幸好后来让我写对象模型写对了。 基类构造期间,虚函数从来不会向下匹配(go down)到派生类。取而代之的是,那个对象的行为就好像它的类型是基类。非正式地讲,基类构造期间,虚函数禁止。 这个表面上看起来匪夷所思的行为存在一个很好的理由。因为基类的构造函数在派生类构造函数之前执行,当基类构造函数运行时,派生类数据成员还没有被初始化。如果基类构造期间调用的虚函数向下匹配(go down)到派生类,派生类的函数理所当然会涉及到本地数据成员,但是那些数据成员还没有被初始化。这就会为未定义行为和悔之晚矣的调试噩梦开了一张通行证。调用涉及到一个对象还没有被初始化的部分自然是危险的,所以 C++ 告诉你此路不通。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |