虛函數地址的找法:
#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;
}
#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.靜態成員函數不能是虛函數,因為靜態成員函數的特點是不受限制于某個對象。
4.內聯(inline)函數不能是虛函數,因為內聯函數不能在運行中動態確定位置。即使虛函數在類的內部定義定義,但是在編譯的時候系統仍然將它看做是非內聯的。
5.構造函數不能是虛函數,因為構造的時候,對象還是一片位定型的空間,只有構造完成后,對象才是具體類的實例。
6.析構函數可以是虛函數,而且通常聲名為虛函數。
------------------------------------
1)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
如果子類中有基類的對象成員,則先調用基類的構造函數,再調用基類的構造函數對基類的對象成員初始化,最后才調用子類的構造函數,析構正好順序相反。
2)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)
在調用變量的時候,要指出時屬于那個類。