基類的建構函式不能被繼承,在宣告派生類時,對繼承過來的成員變數的初始化工作也要由派生類的建構函式來完成。所以在設計派生類的建構函式時,不僅要考慮派生類新增的成員變數,還要考慮基類的成員變數,要讓它們都被初始化。
解決這個問題的思路是:在執行派生類的建構函式時,呼叫基類的建構函式。
下面的例子展示了如何在派生類的建構函式中呼叫基類的建構函式。
#include
using
namespace std;
//基類
class
people
;people::
people
(char
*name,
int age):
name
(name),
age(age)
{}//派生類
class
student
:public people
;//呼叫了基類的建構函式
student::
student
(char
*name,
int age,
float score):
people
(name, age)
void student::
display
()int
main
()
執行結果為:
小明的年齡是16,成績是90.5
請注意**第23行:
student::student(char *name, int age, float score): people(name, age)這是派生類 student 的建構函式的寫法。冒號前面是派生類建構函式的頭部,這和我們以前介紹的建構函式的形式一樣,但它的形參列表包括了初始化基類和派生類的成員變數所需的資料;冒號後面是對基類建構函式的呼叫,這和普通建構函式的引數初始化表非常類似。
實際上,你可以將對基類建構函式的呼叫和引數初始化表放在一起,如下所示:
student::student(char *name, int age, float score): people(name, age), score(score){}基類建構函式和初始化錶用逗號隔開。
需要注意的是:冒號後面是對基類建構函式的呼叫,而不是宣告,所以括號裡的引數是實參,它們不但可以是派生類建構函式總參數列中的引數,還可以是區域性變數、常量等。如下所示:
student::student(char *name, int age, float score): people("李磊", 20)事實上,通過派生類建立物件時必須要呼叫基類的建構函式,這是語法規定。也就是說,定義派生類建構函式時最好指明基類建構函式;如果不指明,就呼叫基類的預設建構函式(不帶引數的建構函式);如果沒有預設建構函式,那麼編譯失敗。
請看下面的例子:
#include
using
namespace std;
//基類
class
people
;people::
people
()people::
people
(char
*name,
int age):
name
(name),
age(age)
{}//派生類
class
student
:public people
;student::
student
()student::
student
(char
*name,
int age,
float score):
people
(name, age)
void student::
display
()int
main
()
執行結果:
***的年齡是0,成績是0
小明的年齡是16,成績是90.5
建立物件 stu1 時,執行派生類的建構函式 student::student(),它並沒有指明要呼叫基類的哪乙個建構函式,從執行結果可以很明顯地看出來,系統預設呼叫了不帶引數的建構函式,也就是 people::people()。
建立物件 stu2 時,執行派生類的建構函式 student::student(char *name, int age, float score),它指明了基類的建構函式。
在第31行**中,如果將 people(name, age) 去掉,也會呼叫預設建構函式,stu2.display() 的輸出結果將變為:
***的年齡是0,成績是90.5
如果將基類 people 中不帶引數的建構函式刪除,那麼會發生編譯錯誤,因為建立物件 stu1 時沒有呼叫基類建構函式。
總結:如果基類有預設建構函式,那麼在派生類建構函式中可以不指明,系統會預設呼叫;如果沒有,那麼必須要指明,否則系統不知道如何呼叫基類的建構函式。為了搞清這個問題,我們不妨先來看乙個例子:
#include
using
namespace std;
//基類
class
people
;people::
people
():name
("***"
),age(0
)people::
people
(char
*name,
int age):
name
(name),
age(age)
//派生類
class
student
:public people
;student::
student
():score
(0.0
)student::
student
(char
*name,
int age,
float score):
people
(name, age),
score
(score)
intmain
()
執行結果:
people::people()
student::student()
--------------------
people::people(char *, int)
student::student(char*, int, float)
從執行結果可以清楚地看到
,當建立派生類物件時,先呼叫基類建構函式,再呼叫派生類建構函式。
如果繼承關係有好幾層的話,例如:
a --> b --> c
那麼則建立c類物件時,建構函式的執行順序為:
a類建構函式 --> b類建構函式 --> c類建構函式
建構函式的呼叫順序是按照繼承的層次自頂向下、從基類再到派生類的。
C 派生類建構函式
派生類構造函式呼叫順序 1.基類的建構函式.2.子物件類的建構函式.3.派生類建構函式.當物件被刪除時,派生類的析構函式被執行,由於析構函式也不能被繼承,因此在執行派生類的析構函式時,基類的析構函式也會被呼叫。先執行派生類的析構函式,再執行子物件類的析構函式,再執行基類的建構函式。include u...
C 派生類的建構函式
1,在使用建構函式的時候,作為派生類會有某些特殊問題。其根源就是建立派生類的時候會有多個建構函式起作用。2,c 中例項化的類的建構函式本身不能初始化類,還必須呼叫基類的建構函式。3,建構函式的呼叫順序是自上向下的,實際上是編譯器先自下而上的尋找建構函式,然後再自上而下的執行 直到達到要例項化的類為止...
C 派生類的 建構函式
問題 希望執行派生類的建構函式時,使派生類的資料成員和基類的資料成員同時初始化 方案 在執行派生 類建構函式時,呼叫基類建構函式 一般形式 派生類建構函式名 總參數列列 基類建構函式名 參數列列 include include using namespace std class student 宣告...