C 中幾個值得分析的小問題(1)

2022-04-12 05:22:39 字數 3056 閱讀 6585

下面3個小問題都是我認為c++ beginner應該能夠解答或辨別清楚的。希望我們能通過題目挖掘更多的資訊,而不僅僅侷限在解題。我最喜歡說的話:

能力有限,所以作為拋磚引玉,希望共同討論,指出錯誤。

另外,我都是碰到乙個覺得有必要記錄的問題,就寫下來說說,所以每一篇內容可能不是單一主題。

1、先來看一道簡單題目。有下面這個繼承類:

class

person

;

};class student : public

person

;

};

你沒看錯

walk()是非虛函式。請解釋下面**:

student s;

person* pp = &s;

pp->walk();

student* ps= &s;

ps->walk();

結果是這樣的:

分析:walk()是非虛函式,被靜態繫結所限制,所以pp、ps是什麼型別就決定了呼叫的版本。這裡,我還要說明的一點是:明白介面繼承和實現繼承。宣告乙個non-virtual函式的目的是為了令derived class繼承函式的介面及乙份強制性實現。所以,絕不要重新定義繼承而來的non-virtual函式

2、下面這個問題實質上也是靜態繫結與動態繫結的問題,但看起來不那麼明顯。

class

shape

; //

形狀顏色

virtual

void draw(shapecolor color = red) const = 0;};

class circle : public

shape

};class rectangle : public

shape

};

我主要想說兩個問題。

(1)當你下面這樣呼叫時,請解釋會發生什麼情況。

circle cr;            //

(1) 編譯不通過

cr.draw();

shape *ps = &cr; //

(2)ps->draw();

沒錯,(1)通過物件呼叫而不指定引數是錯誤的,而(2)的結果是這樣的:color = 0代表red這你應該是知道的。

分析:通過物件呼叫是靜態繫結,一定要指定引數值,因為靜態繫結這個函式不從base class繼承預設引數值。動態繫結卻可以從base class繼承引數值。注意,這裡我就不強調動態繫結和靜態繫結的概念了,但下面這個一定是靜態繫結:

circle cr;

circle *ps = &cr; //

這還是靜態繫結,靜態型別circle *,編譯不通過

ps->draw();

(2)第二個我想說的問題,請解釋下面的呼叫結果。

shape* ps1 = new

rectangle;

ps1->draw();

shape* ps2 = new

circle;

ps2->draw();

是這樣令人可喜的結果:

你是說,你在rectangle中已經將draw的預設值改為1(green)了,怎麼沒效果?

分析:rectangle::draw的預設引數值為green,但ps2的靜態型別為shape*,所以此呼叫的預設引數值來自shape class。

如果你非要讓rectangle::draw的引數有所改變,可以這樣呼叫(提供引數):

shape* ps4 = new

rectangle;

ps4->draw(shape::green);

shape* ps5 = new

circle;

ps5->draw(shape::green);

virtual函式是動態繫結,預設引數值是靜態繫結。所以,不應該重新定義這個預設引數值。3、多重繼承為什麼會含有多個虛表指標而不是乙個?

這道題是我看一位同學面試經驗時,面試官提的,我試著回答一下,不知道在不在點子上,還請補充和指正。

答:多重繼承下,因為編譯器對乙個derived class實現了n-1個虛表,n表示上一層base class的個數,當然假設每個base class都有至少有乙個virtual函式,否則編譯器是不會為其新增vptr和vtbl了。所以說有多少個虛表,自然就有多少個指標指向,而不是乙個。

這樣說我不知道合理不合理,可能面試官要問的點是「為什麼需要多個虛表?乙個虛表行不行?」

這個屬於編譯器廠商做的事情,標準並未規範。c++的父親就做出過這樣的一款編譯器原型,通過增大vtbl的體積,每個slot上不只有乙個指標,還有乙個offset,用來調整this指標的指向。

這樣做的弊端是:所有vtbl中的虛函式指標都包含這樣乙個offset,並且假設不需要調整this指向,呼叫時還是要做offset的加法操作,儘管offset此時為0。另外,vtbl中每個slot體積的膨脹。這些都是效率問題。

實際上,用來調整this的指向用的比較多的是trunk技術,必須以彙編編寫才能獲得高效率。另外,sun編譯器就是把多個虛表連鎖為1個,每個**中含有下乙個**的指標(通過offset方式),這樣就需要乙個指標就好了。

理解能力有限,不知道問的是不是這麼一回事?

目錄:

c++中幾個值得分析的小問題(1)

c++中幾個值得分析的小問題(2)

C 中幾個值得分析的小問題(2)

下面有3個小問題,作為c beginner你一定要知道錯在 了。1 派生類到基類的引用或指標轉換一定 完美 存在?一般情況,你很可能會認為 派生類物件的引用或指標轉換為基類物件的引用或指標是一件很正常的事。那要是不一般情況呢?請看下面這個例子 class person string id 作為一般的...

面試中的幾個小問題

面試中的幾個小問題 1 對stl中list封裝 參考1 2 對重要c函式實現 參考2 memset void memset void buffer,int c,int count memcpy void memcpy void dst,const void src,int count return ...

幾個常見的C 小問題

1.c 引用dll後,未能找到型別或命名空間名稱的問題 解決辦法 注意引用dll的程式集版本與當前程式集是否一致,即目標框架.net framwork版本是否一致。專案屬性 應用程式 解決辦法 把專案中 properties 目錄下的 license.licx 檔案刪除,再編譯就成功了。4.c 程式...