虛函數相關問題分析,函數相關問題分析

來源:互聯網
上載者:User

虛函數相關問題分析,函數相關問題分析
1、靜態聯編和動態聯編
將原始碼中的函數調用解釋為執行特定的函數代碼塊被稱為函數名聯編。在C語言中,這非常簡單,因為每個函數名都對應於一個不同的函數。在C++中,由於函數重載的緣故,這項任務更複雜。編譯器必須查看函數參數以及函數名才能確定使用哪個函數。然而,C/C++編譯器可以在編譯過程中完成這種聯編。在編譯過程中進行聯編稱為靜態聯編,又稱為早期聯編。不過虛函數使這項工作變得更困難。因為編譯器不知道將選擇哪種類型的對象。所以,編譯器必鬚生成能夠在程式運行時選擇正確的虛方法的代碼,這被稱為動態聯編,又稱為晚期聯編。
2、指標和參考型別相容性
通常,C++不允許將一種類型的地址賦給另一種類型的指標,也不允許一種類型的引用指向另一種類型:
double x = 2.5;
int* pi = &x;//invalid assignment
long& r1 = x;//invalid assignment
不過,正如我們看到的,指向基類的引用或指標可以引用衍生類別對象,而不必進行顯示類型轉換。
將衍生類別引用或指標轉換為基類引用或指標被稱為向上強制轉換,這使公有繼承不需要進行顯示類型轉換。該規則是is-a關係的一部分。向上強制轉換時可傳遞的,也就是說,如果A派生出B,B派生出C,則A指標或引用可以引用A對象、B對象或C對象。
相反的過程---將基類指標或引用轉換為衍生類別指標或引用---稱為向下強制轉換,如果不使用顯示類型轉換,則向下強制轉換時不允許的。
3、編譯器對非虛方法使用靜態聯編,對虛方法使用動態聯編。C++編譯器預設使用靜態聯編。
4、虛函數的工作原理
通常,編譯器處理虛函數的方法是:給每個對象添加一個隱藏成員,隱藏成員中儲存了一個指向函數地址數組的指標。這種數組稱為虛函數表。虛函數表中儲存了為類對象進行生明的虛函數的地址。例如,基類對象包含一個指標,該指標指向基類中所有虛函數的地址表。衍生類別對象將包含一個指向獨立地址表的指標。如果衍生類別提供了虛函數的新定義,該虛函數表將儲存新函數的地址;如果衍生類別沒有重新定義虛函數,該虛函數表將儲存函數原始版本的地址。如果衍生類別定義了新的虛函數,則該函數的地址也將被添加到虛函數表中。
5、注意事項
如果在衍生類別中重新定義函數,將不是使用相同的函數特徵標覆蓋基類聲明,而是隱藏同名的基類方法,不管參數特徵標如何。這將引出兩條經驗規則:
①如果重新定義繼承的方法,應確保與原來的原型完全相同,但如果傳回型別是基類引用或指標,則可以修改為指向衍生類別的引用或指標。這種特性被稱為傳回型別協變,因為允許傳回型別隨類類型的變化而變化。
②如果基類聲明被重載了,則應在衍生類別中重新定義所有的基類版本。如果只重新定義一個版本,則另外兩個版本將被隱藏,衍生類別對象將無法使用它們。
虛函數的概念與特性?

定義
虛函數必須是基類的非靜態成員函數,其存取權限可以是protected或public,在基類的類定義中定義虛函數的一般形式: virtual 函數傳回值類型 虛函數名(形參表) { 函數體 }
編輯本段作用
虛函數的作用是實現動態聯編,也就是在程式的運行階段動態地選擇合適的成員函數,在定義了虛函數後,可以在基類的衍生類別中對虛函數重新定義,在衍生類別中重新定義的函數應與虛函數具有相同的形參個數和形參類型。以實現統一的介面,不同定義過程。如果在衍生類別中沒有對虛函數重新定義,則它繼承其基類的虛函數。 當程式發現虛函數名前的關鍵字virtual後,會自動將其作為動態聯編處理,即在程式運行時動態地選擇合適的成員函數。 ([2010.10.28] 註:下行語義容易使人產生理解上的偏差,實際效果應為: 如存在:Base -> Derive1 -> Derive2 及它們所擁有的虛函數func() 則在訪問衍生類別Derive1的執行個體時,使用其基類Base及本身類型Derive1,或被靜態轉換的後續衍生類別Derive2的指標或引用,均可訪問到Derive1所實現的func()。) 動態聯編規定,只能通過指向基類的指標或基類對象的引用來調用虛函數,其格式: 指向基類的指標變數名->虛函數名(實參表) 或 基類對象的引用名. 虛函數名(實參表) 虛函數是C++多態的一種表現 例如:子類繼承了父類的一個函數(方法),而我們把父類的指標指向子類,則必須把父類的該函數(方法)設為virtual(虛函數)。 使用虛函數,我們可以靈活的進行動態綁定,當然是以一定的開銷為代價。 如果父類的函數(方法)根本沒有必要或者無法實現,完全要依賴子類去實現的話,可以把此函數(方法)設為virtual 函數名=0 我們把這樣的函數(方法)稱為純虛函數。 如果一個類包含了純虛函數,稱此類為抽象類別 。
編輯本段樣本
虛函數的執行個體
#include<iostream.h> class Cshape { public: void SetColor( int color) { m_nColor=color;} void virtual Display( void) { cout<<"Cshape"<<endl; } private: int m_nColor; }; class Crectangle: public Cshape { public: void virtual Display( void) { cout<<"Crectangle"<<endl; } }; class Ctriangle: public Cshape { void virtual Display( void) { cout<<"Ctriangle"<<endl; } }; class Cellipse :public Cshape { public: void virtual Display(void) { cout<<"Cellipse"<<endl;} }; void main() { Cshape obShape; Cellipse obEllipse; ......餘下全文>>
 
C++中虛函數的作用是什?它應該怎使用?

虛函數聯絡到多態,多態聯絡到繼承。所以本文中都是在繼承層次上做文章。沒了繼承,什麼都沒得談。

下面是對C++的虛函數這玩意兒的理解。

一, 什麼是虛函數(如果不知道虛函數為何物,但有急切的想知道,那你就應該從這裡開始)

簡單地說,那些被virtual關鍵字修飾的成員函數,就是虛函數。虛函數的作用,用專業術語來解釋就是實現多態性(Polymorphism),多態性是將介面與實現進行分離;用形象的語言來解釋就是實現以共同的方法,但因個體差異而採用不同的策略。下面來看一段簡單的代碼

class A{

public:

void print(){ cout<<”This is A”<<endl;}

};

class B:public A{

public:

void print(){ cout<<”This is B”<<endl;}

};

int main(){ //為了在以後便於區分,我這段main()代碼叫做main1

A a;

B b;

a.print();

b.print();

}

通過class A和class B的print()這個介面,可以看出這兩個class因個體的差異而採用了不同的策略,輸出的結果也是我們預料中的,分別是This is A和This is B。但這是否真正做到了多態性呢?No,多態還有個關鍵之處就是一切用指向基類的指標或引用來操作對象。那現在就把main()處的代碼改一改。

int main(){ //main2

A a;

B b;

A* p1=&a;

A* p2=&b;

p1->print();

p2->print();

}

運行一下看看結果,喲呵,驀然回首,結果卻是兩個This is A。問題來了,p2明明指向的是class B的對象但卻是調用的class A的print()函數,這不是我們所期望的結果,那麼解決這個問題就需要用到虛函數

class A{

public:

virtual void print(){ cout<<”This is A”<<endl;} //現在成了虛函數了

};

class B:public A{

public:

void print(){ cout<<”This is B”<<endl;} //這裡需要在前面加上關鍵字virtual嗎?

};

毫無疑問,class A的成員函數print()已經成了虛函數,那麼class B的print()成了虛函數了嗎?回答是Yes,我們只需在把基類的成員函數設為virtual,其衍生類別的相應的函數也會自動變為虛函數。所以,class B的print()也成了虛函數。那麼對於在衍生類別的相應函數前是否需要用virtual關鍵字修飾,那就是你自己的問題了。

現在重新運行main2的代碼,這樣輸出的結果就是This is A和This is B了。

現在來消化一下,我作個簡單的總結,指向基類的指標在操作它的多態類對象時,會根據不同的類對象,調用其相應的函數,這個函數就是虛函數。

二, 虛函數是如何做到的(如果你沒有看過《Inside The C++ Object Model》這本書,但又急切想知道,那你就應該從這裡開始)

虛函數是如何做到因對象的不同而調用其相應的函數的呢?現在我們就來剖析虛函數......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.