虛函數(shù)地址的找法:
#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);//找到第一個虛函數(shù)的地址
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);//找到第一個虛函數(shù)的地址
num2=*(long*)(*(long*)derived);
cout<<num1<<endl;
cout<<num2<<endl;
return 0;
}
---------------------------------------
虛函數(shù)的定義要遵循以下重要規(guī)則:
1.如果虛函數(shù)在基類與派生類中出現(xiàn),僅僅是名字相同,而形式參數(shù)不同,或者是返回類型不同,那么即使加上了virtual關(guān)鍵字,也是不會進行滯后
聯(lián)編的。
2.只有類的成員函數(shù)才能說明為虛函數(shù),因為虛函數(shù)僅適合用與有繼承關(guān)系的類對象,所以普通函數(shù)不能說明為虛函數(shù)。
3.靜態(tài)成員函數(shù)不能是虛函數(shù),因為靜態(tài)成員函數(shù)的特點是不受限制于某個對象。
4.內(nèi)聯(lián)(inline)函數(shù)不能是虛函數(shù),因為內(nèi)聯(lián)函數(shù)不能在運行中動態(tài)確定位置。即使虛函數(shù)在類的內(nèi)部定義定義,但是在編譯的時候系統(tǒng)仍然將它看做是非內(nèi)聯(lián)的。
5.構(gòu)造函數(shù)不能是虛函數(shù),因為構(gòu)造的時候,對象還是一片位定型的空間,只有構(gòu)造完成后,對象才是具體類的實例。
6.析構(gòu)函數(shù)可以是虛函數(shù),而且通常聲名為虛函數(shù)。
------------------------------------
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;//因為基類的析構(gòu)不是虛,如 是則先調(diào)用子類的析構(gòu)
//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
如果是子類構(gòu)造先基類,再子類
如果是子類析構(gòu)先子類,再基類
但如果基類析構(gòu)不是虛,則CBase *pBase2= new CDerived;
delete pBase2;只調(diào)用基類.否則如果基類析構(gòu)是虛,則先調(diào)用子類,再調(diào)用基類。
如果是用new初始化的,必須用delete來釋放,否則不調(diào)用析構(gòu)函數(shù)。
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
如果子類中有基類的對象成員,則先調(diào)用基類的構(gòu)造函數(shù),再調(diào)用基類的構(gòu)造函數(shù)對基類的對象成員初始化,最后才調(diào)用子類的構(gòu)造函數(shù),析構(gòu)正好順序相反。
2)CBase1:public CBase
CBase2:public CBase
CDervied:public CBase1,CBase2
CDerived pdereved;
如果沒有定義為虛繼承 ,先調(diào)用基類再子類然后再基類再子類最后才調(diào)用子子類構(gòu)造。
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,則只調(diào)用一次基類
CBase::CBase()!
CBase1::CBase()!
CBase2::CBase()!
CDerived::CDerived()!
CDerived::~CDerived()!
CBase2::~CBase()!
CBase1::~CBase()!
CBase::~CBase()!
Press any key to continue
-----------------------------------
多重繼承的成員調(diào)用:
cbase
CBase1:public CBase
CBase2:public CBase
CDervied:public CBase1,CBase2
1)當(dāng)cbase1與cbase2不是虛繼承的時:dervied不能訪問基類繼承而來(即共有的)的任何成員,不能識別。
2)當(dāng)cbase1與cbase2是虛繼承的時,dervied可以訪問cbase中沒有1和2重新定義的成員,也能訪問只被1或只被2重新定義的成員,這是調(diào)用1或2中的成員,當(dāng)dervied中有重寫時,調(diào)用derived中重新定義的成員。(共有)
:保證我們在不考慮繼承而來的隱藏成員時,能夠識別該調(diào)用那個類中的!則編譯器也能識別!
3)
在調(diào)用變量的時候,要指出時屬于那個類。