C 函式覆蓋的思考

2022-05-06 18:45:11 字數 1902 閱讀 1640

最近碰到一些問題,一開始很難除錯和解決,最後發現原來是在基類函式的模板方法中對子類需要重寫的函式沒有使用virtual,如下

class

base

void

test(){}

};class child : public

base

};

準備用template method的我很有自信的敲著自己的**,期待在

child a;

a.say();

的時候,a會去最終呼叫child的test。注意,這裡面沒有牽扯到任何基類指標乃至基類引用指向子類的概念,純粹是乙個child實體,我一廂情願的以為a的say在進入base的say之後,會去呼叫child的test.因為它本身就是child嘛~但就是這麼個很小的細節,讓我的問題在出現的時候我很難理解。真實的情況是此時的test實際呼叫的是base的test。但如果我們換個寫法

class

base

virtual

void

test(){}

};class child : public

base

};

此時a.test會去最終呼叫child的test。為什麼,這裡面根本就沒有基類指標或者基類引用去指向子類的過程啊!虛函式的實現不是一定要通過指標或者引用嗎?純粹這樣的實體類為什麼也會採取動態繫結?

其實這也只能怪自己讀書太膚淺,一直天真的以為動態繫結的實現必須滿足兩個先天條件。即virtual關鍵字的滿足和基類指標和引用的滿足。其實我們錯了,c++中對應virtual機制來說,不過你是不是指標或者引用,只要你是child實體並且滿足virtual重寫父類,那麼無論如何,都會進入到你自己的函式當中去。因此,當我們要實現設計模式中模板方法模式的時候,不要懷疑和猶豫我此時需要子類實現的函式要不要虛函式,因為答案一定是一定要。你可以考慮這樣的情況,其實只有兩種方法會真正用到子類,一種是基類指標或者引用,一種就是子類實體本身,結合上文案例,不管這兩種情況你採用哪種,當對應到test進行選擇的時候,如果你用virtual都會根據最終的實際型別去選擇,這就是區別。

再比如,當我們要抽象a與b提煉公共類c的時候,其實不需要考慮到底外部會不會對c進行呼叫,就算沒有對c進行引用,一旦你做了公共分離,你就會在公共**中去呼叫你子類的函式,此時你的公共類中必然有這個函式的空定義或者介面,你可以考慮如果不進行virtual修飾那情況會是什麼樣。比如

class

c

void

test();

};classa;

class

b;

你將公共**的say進行提煉到父類c的時候,當外界對你的a進行a.say(),自然而然會去呼叫c的say,但這個時候,裡面的test要注意不是virtual,為什麼會出現這種選擇?因為我們在做抽象分離的時候確實會去考慮這個問題----倘若外界沒有對我公共介面的訪問,我還需要虛函式嗎?

答案很明顯已經出來了,結合上文,即使你外界沒有對你的c進行任何介面呼叫,你的a或者b都是寫死的,比如a a; b c;沒有 c *a = new a等,你也務必需要在提取公共類的時候顯示加上virtual

class

c

virtual

void

test();

};classa;

class

b;

因為只有這樣,外界對a進行say訪問的時候,最終的test才會調到它自己,否則,就會去調c的test。

總結,歸根結底,c++的virtual並不是說一定要和基類指標或者引用掛鉤才會起作用(其實很多介紹多型的書在舉例子的時候大多採用這種寫法因此會給我們帶來一定誤導,讓我們始終認為這兩個條件的必要性),其實哪怕只是例項,也是需要將virtual考慮在內的。

C 函式覆蓋

覆蓋類成員 通過new關鍵字修飾虛函式表示覆蓋該虛函式。乙個虛函式被覆蓋後,任何父類變數都不能訪問該虛函式的具體實現。public virtual void introducemyself 父類虛函式 public new void introducemyself 子類覆蓋父類虛函式 using s...

C 函式過載和函式覆蓋的區別

overload 翻譯過來就是 超載,過載,過載,超出標準負荷 override 翻譯過來是 重置,覆蓋,使原來的失去效果。先來說說過載的含義,在日常生活中我們經常要清洗一些東西,比如洗車 洗衣服。儘管我們說話的時候並沒有明確地說用 洗車的方式來洗車,或者用洗衣服的方式來洗一件衣服,但是誰也不會用洗...

c 函式過載和函式覆蓋的區別

overload 翻譯過來就是 超載,過載,過載,超出標準負荷 override 翻譯過來是 重置,覆蓋,使原來的失去效果。先來說說過載的含義,在日常生活中我們經常要清洗一些東西,比如洗車 洗衣服。儘管我們說話的時候並沒有明確地說用 洗車的方式來洗車,或者用洗衣服的方式來洗一件衣服,但是誰也不會用洗...