標籤:一個 執行 成員變數 功能 efault col 繼承 his ase
參考:http://www.weixueyuan.net/view/6363.html
總結:
在codingbook類中新增了一個language成員變數,為此必須重新設計新的建構函式。在本例中book類中有一個預設建構函式和一個帶參數的建構函式,codingbook類中同樣聲明了兩個建構函式,一個預設建構函式和一個帶參數的建構函式,預設建構函式顯式調用基類的預設建構函式,帶參建構函式顯式調用基類的帶參建構函式。
codingbook():book(){lang = none;} //定義衍生類別的建構函式時 顯示調用 基類的建構函式
codingbook::codingbook(language lang, char * t, double p):book(t,p)
如果繼承關係有好幾層的話,例如A類派生出B類,B類派生出C類,則建立C類對象時,建構函式的執行順序則為A的建構函式,其次是B的建構函式,最後是C類的建構函式。建構函式的調用順序是按照繼承的層次,自頂向下,從基類再到衍生類別的。
在前一章節中,我們介紹了建構函式的功能和用法,衍生類別同樣有建構函式。當我們建立一個衍生類別對象的時候,基類建構函式將會被自動調用,用於初始化衍生類別從基類中繼承過來的成員變數。而衍生類別中新增的成員變數則需要重新定義建構函式用於初始化了。
例1:
#include<iostream>using namespace std;class book{public: book(); book(char* a, double p = 5.0); void setprice(double a); double getprice()const; void settitle(char* a); char * gettitle()const; void display();private: double price; char * title;};class book_derived :public book{public: void display();};book::book(char* a, double p) { title = a; price = p;}book::book(){ title = "NoTitle"; price = 0.0;}void book::setprice(double a){ price = a;}double book::getprice()const{ return price;}void book::settitle(char* a){ title = a;}char * book::gettitle()const{ return title;}void book::display(){ cout<<"The price of "<<title<<" is $"<<price<<endl;}void book_derived::display(){ cout<<"The price of "<<gettitle()<<" is $"<<getprice()<<endl;}int main(){ book_derived b; b.display(); return 0;}
在本例中定義了book_derived類,該類沒有自身的成員變數,類中所有成員變數都繼承自book類,類中成員函數僅有一個display函數,該函數遮蔽了基類book中的display函數。在主函數中定義衍生類別的對象b,之後調用衍生類別的display函數,程式運行結果為:“The price of NoTitle is $0”。
從這例1中,我們不難看出衍生類別在建立對象時會自動調用基類建構函式。如果像例1這種情況,衍生類別中沒有新增成員變數,基類的建構函式功能已經滿足衍生類別建立對象初始化需要,則衍生類別則無需重新自訂一個建構函式,直接調用基類建構函式即可。如果衍生類別中新增了成員變數,這時如果需要在建立對象時就進行初始化則需要自己設計一個建構函式,具體見例2。
例2:
#include<iostream>using namespace std;enum language{none, cpp, java, python, javascript, php, ruby};class book{public: book(); book(char* a, double p = 5.0); void setprice(double a); double getprice()const; void settitle(char* a); char * gettitle()const; void display();private: double price; char * title;};class codingbook: public book{public : codingbook():book(){lang = none;} codingbook(language lang, char * t, double p); void setlang(language lang); language getlang(){return lang;} void display();private: language lang;};book::book(char* a, double p) { title = a; price = p;}book::book(){ title = "NoTitle"; price = 0.0;}void book::setprice(double a){ price = a;}double book::getprice()const{ return price;}void book::settitle(char* a){ title = a;}char * book::gettitle()const{ return title;}void book::display(){ cout<<"The price of "<<title<<" is $"<<price<<endl;}void codingbook::setlang(language lang){ this->lang = lang;}codingbook::codingbook(language lang, char * t, double p):book(t,p){ this->lang = lang;}void codingbook::display(){ book::display(); cout<<"The language is "<<lang<<endl; }int main(){ codingbook cpp; cpp.display(); codingbook java(java, "Thinking in Java", 59.9); java.display(); return 0;}
本例中定義了兩個類book類和codingbook類,codingbook類是book類的衍生類別。在codingbook類中新增了一個language成員變數,為此必須重新設計新的建構函式。在本例中book類中有一個預設建構函式和一個帶參數的建構函式,codingbook類中同樣聲明了兩個建構函式,一個預設建構函式和一個帶參數的建構函式,預設建構函式顯式調用基類的預設建構函式,帶參建構函式顯式調用基類的帶參建構函式。在主函數中定義了codingbook類的對象cpp,該對象調用codingbook類的預設建構函式,codingbook類中的預設建構函式先會調用基類的預設建構函式將title和price進行初始化,之後才會執行自身函數體中的內容。之後又定義了codingbook類對象java,該對象在定義時後面接有三個參數,很明顯是需要調用codingbook類的帶參建構函式,其中java參數用於初始化lang成員變數,而後兩個參數則用於初始化從基類繼承過來的title和price兩個成員變數,當然初始化順序依然是先調用基類的帶參建構函式初始化title和price,然後再執行自身函數體中的初始化代碼初始化lang成員變數。
最後程式運行結果如下:
The price of NoTitle is $0
The language is 0
The price of Thinking in Java is $59.9
The language is 2
在這個例子中language沒有顯示為java或者cpp,只顯示為0和2,這個熟悉枚舉類型的應該都清楚,枚舉類型在本例中其實就是從0開始的int類型。
從例2中,我們可以很清楚的看到,當我們建立衍生類別對象時,先由衍生類別建構函式調用基類建構函式,然後再執行衍生類別建構函式函數體中的內容,也就是說先執行基類建構函式,然後再去執行衍生類別建構函式。如果繼承關係有好幾層的話,例如A類派生出B類,B類派生出C類,則建立C類對象時,建構函式的執行順序則為A的建構函式,其次是B的建構函式,最後是C類的建構函式。建構函式的調用順序是按照繼承的層次,自頂向下,從基類再到衍生類別的。
例3:
#include<iostream>using namespace std;class base{public: base(){x = 0; y = 0; cout<<"base default constructor"<<endl;} base(int a, int b){x = a; y = b; cout<<"base constructor"<<endl;}private: int x; int y;};class derived: public base{public: derived():base(){z = 0; cout<<"derived default constructor"<<endl;} derived(int a, int b, int c):base(a,b){z = c; cout<<"derived constructor"<<endl;}private: int z;};int main(){ derived A; derived B(1,2,3); return 0;}
本例中定義了兩個類,基類base中定義了一個預設建構函式和一個帶參數的建構函式。衍生類別derived中同樣定義了兩個建構函式,這兩個建構函式一個為預設建構函式,一個為帶參建構函式。衍生類別中的預設建構函式顯式調用基類預設建構函式,帶參建構函式顯式調用基類的帶參建構函式。我們在主函數中定義了衍生類別的兩個對象,這兩個對象一個是調用衍生類別的預設建構函式,另一個調用衍生類別的帶參建構函式。
這個程式運行結果如下:
base default constructor
derived default constructor
base constructor
derived constructor
從運行結果可以看出建立對象時先是執行基類的建構函式,然後再是執行拍攝呢類建構函式。建構函式執行順序是按照繼承順序自頂向下執行。
3.6 C++繼承機制下的建構函式