/* * test virtual functions */#include <iostream>usingnamespacestd;classbase{public:virtualvoidf(){cout<<"in base:f"<<endl;}};classderived:publicbase{public:virtualvoidf(){cout<<"in derived:f"<<endl;}};typedefvoid(*fun)(void);#define VTAB(pclass) ((long*)(*(long*)(pclass)))intmain(void){base*pb=newbase();pb->f();base*pd=(base*)newderived();pd->f();cout<<"--- call through vtable ---"<<endl;funpfun=(fun)*VTAB(pd);pfun();pfun=(fun)*VTAB(pb);pfun();derived*pd_fake=(derived*)pb;pfun=(fun)*VTAB(pd_fake);pfun();pfun=(fun)*VTAB(pd);cout<<"value of *pfun is: "<<*pfun<<endl;pfun=(fun)*(VTAB(pd)+1);cout<<"value of *pfun is: "<<*pfun<<endl;}
/* * 研究构造函数的调用顺序 * 1. 首先调用基类的构造函数(如果有基类);如果有多个基类,则按基类被列出的顺序调用; * 2. 调用这个类的成员对象的构造函数(如果有的话);如果有多个成员对象,则按成员对象定义的顺序被调用(与参数列表中列出的顺序无关); * 3. 最后调用这个类自身的构造函数; * 4. 析构函数正好相反; * 注意:如果有虚基类,则先调用虚基类的构造函数。在调用基类的构造函数,如果有多个虚基类,则按列出的顺序调用; */#include <iostream>usingnamespacestd;classfather_base_a{public:father_base_a(){cout<<"This is father_base_a;"<<endl;}virtual~father_base_a(){cout<<"This is ~father_base_a"<<endl;}};classbase_a:publicfather_base_a{public:base_a(){cout<<"This is base_a;"<<endl;}virtual~base_a(){cout<<"This is ~base_a"<<endl;}};classbase_b{public:base_b(){cout<<"This is base_b;"<<endl;}virtual~base_b(){cout<<"This is ~base_b"<<endl;}};classmember_a{public:member_a(){cout<<"This is meber_a;"<<endl;}virtual~member_a(){cout<<"This is ~meber_a;"<<endl;}};classmember_b{public:member_b(){cout<<"This is member_b;"<<endl;}virtual~member_b(){cout<<"This is ~meber_b;"<<endl;}};classderived:publicbase_b,publicbase_a{public:member_ama;derived(){cout<<"This is derived;"<<endl;}virtual~derived(){cout<<"this is ~derived()"<<endl;}private:member_bmb;};intmain(void){derivedde;cout<<"---------"<<endl;}
/* * 测试c++隐藏规则: * (1)如果派生类的函数与基类的函数同名,但是参数不同。 * 不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。 * (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数 * 没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。 */#include <iostream>usingnamespacestd;classBase{public:virtualvoidf(floatx){cout<<"Base::f(float) "<<x<<endl;}voidg(floatx){cout<<"Base::g(float) "<<x<<endl;}voidh(floatx){cout<<"Base::h(float) "<<x<<endl;}voidm(floatx){cout<<"Base::m(float) "<<x<<endl;}};classDerived:publicBase{public:virtualvoidf(floatx){cout<<"Derived::f(float) "<<x<<endl;}voidg(intx){cout<<"Derived::g(int) "<<x<<endl;}voidh(floatx){cout<<"Derived::h(float) "<<x<<endl;}voidm(intx){cout<<"Derived::m(int) "<<x<<endl;}};intmain(void){Derivedd;Base*pb=&d;Derived*pd=&d;// Good : behavior depends solely on type of the objectpb->f(3.14f);// Derived::f(float) 3.14pd->f(3.14f);// Derived::f(float) 3.14// Bad : behavior depends on type of the pointerpb->g(3.14f);// Base::g(float) 3.14pd->g(3.14f);// Derived::g(int) 3 (surprise!)// Bad : behavior depends on type of the pointerpb->h(3.14f);// Base::h(float) 3.14 (surprise!)pd->h(3.14f);// Derived::h(float) 3.14// Bad : behavior depends on type of the pointerpb->m(3.14f);// Base::m(float) 3.14pd->m(3.14f);// Derived::m(int) 3 (surprise!)}