#include "stdafx.h" #include <iostream> using namespace std; class CBase { public: virtual void who(){cout<<"CBase"<<endl;} }; class CDerived:public CBase { public: virtual void who(){cout<<"CDerived"<<endl;} }; int _tmain(int argc, _TCHAR* argv[]) { long num1=0; long num2=0; CBase *base=new CBase;//必须用new后,才可以找到 CDerived *derived=new CDerived; num1=*(long*)(*(long*)base);//找到第一个虚函数的地址 num2=*(long*)(*(long*)derived); cout<<num1<<endl; cout<<num2<<endl; return 0; }
---------------------------------------
1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行滞后
联编的。
2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。(
在C++中静态成员函数也是类函数,及这个函数不属于某个具体的对象,而是属于一个类的,这个类实例化的每个成员都可用,同时,这个类也可以直接调用这个函数而不用实例化一个对象。
)
4.内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义定义,但是在编译的时候系统仍然将它看做是非内联的。
5.构造函数不能是虚函数,因为构造的时候,对象还是一片位定型的空间,只有构造完成后,对象才是具体类的实例。
6.析构函数可以是虚函数,而且通常声名为虚函数。
------------------------------------
Derived:public Base CBase pBase; CDerived pDerived; CBase *pBase2= new CDerived; delete pBase2; CDerived pDerived2; //results: //CBase::CBase // CBase pBase; //CBase::CBase //CDerived pDerived; //CDerived:: CDerived //CBase::CBase //CBase *pBase2= new CDerived; //CDerived:: CDerived //CBase::~CBase // delete pBase2;//因为基类的析构不是虚,如 是则先调用子类的析构 //CBase::CBase //CDerived pDerived2; //CDerived:: CDerived //CDerived::~CDerived //CDerived pDerived2; //CBase::~CBase //CDerived::~CDerived //CDerived pDerived; //CBase::~CBase //CBase::~CBase //CBase pBase; //Press any key to continue 如果是子类构造先基类,再子类 如果是子类析构先子类,再基类 但如果基类析构不是虚,则CBase *pBase2= new CDerived; delete pBase2;只调用基类.否则如果基类析构是虚,则先调用子类,再调用基类。 如果是用new初始化的,必须用delete来释放,否则不调用析构函数。 CDerived pDerived(10);//the base class must be have the defaut constructor //CBase::CBase //this is defuat constructor function //CDerived:: CDerived //CDerived::~CDerived //CBase::~CBase //CBase::~CBase //Press any key to continue
如果子类中有基类的对象成员,则先调用基类的构造函数,再调用基类的构造函数对基类的对象成员初始化,最后才调用子类的构造函数,析构正好顺序相反。
CBase1:public CBase CBase2:public CBase CDervied:public CBase1,CBase2 CDerived pdereved; 如果没有定义为虚继承 ,先调用基类再子类然后再基类再子类最后才调用子子类构造。 CBase::CBase()! CBase1::CBase()! CBase::CBase()! CBase2::CBase()! CDerived::CDerived()! CDerived::~CDerived()! CBase2::~CBase()! CBase::~CBase()! CBase1::~CBase()! CBase::~CBase()! Press any key to continue 如果cbase1与cbase2是虚继承cbase,则只调用一次基类 CBase::CBase()! CBase1::CBase()! CBase2::CBase()! CDerived::CDerived()! CDerived::~CDerived()! CBase2::~CBase()! CBase1::~CBase()! CBase::~CBase()!
Press any key to continue
-----------------------------------
多重继承的成员调用:
cbase
CBase1:public CBase
CBase2:public CBase
CDervied:public CBase1,CBase2
1)当cbase1与cbase2不是虚继承的时:dervied不能访问基类继承而来(即共有的)的任何成员,不能识别。
2)当cbase1与cbase2是虚继承的时,dervied可以访问cbase中没有1和2重新定义的成员,也能访问只被1或只被2重新定义的成员,这是调用1或2中的成员,当dervied中有重写时,调用derived中重新定义的成员。(共有)
:保证我们在不考虑继承而来的隐藏成员时,能够识别该调用那个类中的!则编译器也能识别!
3)
在调用变量的时候,要指出时属于那个类。
原文:http://blog.csdn.net/u010236550/article/details/19069067