C++難點的一些總結


一、 C++成員函數的重載

C++中的成員函數有四種,分別是普通成員函數,virtual虛函數,const成員函數。

(1) void func(int a);

(2) virtual void func(int a);

(3) void func(int a) const;

如果在一個類中,聲明這四種函數,哪是重復定義?哪些是重載?

其中(1)(2)是重復定義,故編譯不能通過,而(3)與(1)(2)是不同類型的函數,是重載。

【注意:眾所周知,C++函數重載時返回值是不參與重載決議的, 也就是說,

int lex_cast(const char*);

double lex_cast(const char*);

這樣兩個函數在同一個編譯單元同一個 namespace 中時, 會編譯報錯。

成員函數被重載的特征是:

(1)具有相同的作用域(即同一個類定義中);

(2)函數名字相同

(3)參數類型,順序 或 數目不同(包括const參數和非const函數)

(4)virtual關鍵字可有可無。

從成員函數的重載特征中,可以知道(1)(2)是重復定義。那么(3)為什么和(1)(2)不同呢?

因為類中的函數,都會自動添加一個自身類指針this,所以

void func(int a) ==== void func(Base * this, int a)

virtual func(int a) ==== virtual func(Base *this, int a)

void func(int a)const  ===  void func(const Base *this, int a) const  【重要】

所以(3)可以與(1)(2)發生重載,因為參數有一個const。

 

二、inline, static, constructor三種函數都不能帶有virtual關鍵字

(1).為什么C++不支持構造函數為虛函數?

這個原因很簡單,主要是從語義上考慮,所以不支持。因為構造函數本來就是為了明確初始化對象成員才產生的,然而virtual function主要是為了再不完全了解細節的情況下也能正確處理對象。另外,virtual函數是在不同類型的對象產生不同的動作,現在對象還沒有產生,如何使用virtual函數來完成你想完成的動作。(這不就是典型的悖論)

【最簡單是因為,類中只有構造、析構和拷貝構造三個函數不能被繼承,所以每個類都必須有明確的編譯期就確定的上述三個函數,沒有的會自動生成。】

(2).為什么C++不支持內聯成員函數為虛函數?

其實很簡單,那內聯函數就是為了在代碼中直接展開,減少函數調用花費的代價,虛函數是為了在繼承后對象能夠准確的執行自己的動作,這是不可能統一的。(再說了,inline函數在編譯時被展開,虛函數在運行時才能動態的邦定函數)

4.為什么C++不支持靜態成員函數為虛函數?

這也很簡單,靜態成員函數對於每個類來說只有一份代碼,所有的對象都共享這一份代碼,他也沒有要動態邦定的必要性。【只是因為沒有太大必要性所以這樣,這條可以死記住。因為實際上是可以實現的,技術上沒什么問題,就是為了邏輯性而強制這樣規定了。】

5.(補充)為什么C++不支持友元函數為虛函數?

因為C++不支持友元函數的繼承,對於沒有繼承特性的函數沒有虛函數的說法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM