基類和派生類
繼承允許我們依據另一個類來定義一個類,這使得創建和維護一個應用程式變得更容易,這樣做,也達到了重用代碼功能和提高執行時間的效果,
當創建一個類時,您不需要重新撰寫新的資料成員和成員函式,只需指定新建的類繼承了一個已有的類的成員即可,這個已有的類稱為基類,新建的類稱為派生類,
C++中有分三種繼承方式,如下表所示,

這里不去過多地討論什么是繼承,這里對繼承時產生的一些事進行討論,
繼承時,建構式做了什么
話不多說,上代碼
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout<<"this is Father()"<<endl;
}
};
class Son : public Father
{
public:
Son()
{
cout<<"this is son()"<<endl;
}
};
int main()
{
Son p;
return 0;
}
運行結果
this is Father()
this is son()
在上面的代碼中,我在Father這個基類,和Son這個派生類里面分別添加了建構式,在主程式里面定義了一個派生類的實體化物件,然而從運行結果里發現,分別進行了Father的建構式和Son的建構式,從而得出結論:在定義基類的實體化物件時,不僅會執行自身的建構式,還會執行派生類的建構式,
既然執行了建構式,那么他們執行的先后順序是什么樣的呢,從上述的代碼中,可以看出基類的建構式是執行在派生類之前的,那么遇到多個繼承關系,他們的繼承關系又是什么樣的呢?
為了內容不那么長,這里省略部分代碼
class GrandFather{...};
class Mother : public GrandFather{...};
class Mr_Wang {};
class Son : public GrandFather, virtual public Mr_Wang{...};
int main()
{
Son s;
return 0;
}
由上述程式可見,繼承關系如圖所示

這里Mr_Wang和Son的關系是虛擬繼承(虛擬繼承不在本次討論范圍內),所以這里用紅色表示,
程式的運行結果如下
Mr_Wang
GrandFather
mother
Son
從運行結果中,不難看出
虛擬繼承建構式的優先級最高,其次,基類的優先級會高于派生類
使用基類指標指向派生類,會發生什么
下面分兩點來討論
使用基類指標指向派生類,建構式的順序是什么樣
話不多說,依舊上代碼
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout<<"this is Father()"<<endl;
}
};
class Son : public Father
{
public:
Son()
{
cout<<"this is son()"<<endl;
}
};
int main()
{
Father *p = new Son;
delete p;
p = NULL;
return 0;
}
執行結果
this is Father()
this is son()
從運行結果中,不難看出,基類指標指向派生類,建構式還是會先構造基類,再構造派生類,
使用基類指標指向派生類,對于屬性的訪問是什么樣的
這里先說結論:使用基類指標指向派生類,該指標只能參考基類成員,
下面修改代碼
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout<<"this is Father()"<<endl;
}
void test_func_one()
{
cout<<"this is test_func_one";
}
};
class Son : public Father
{
public:
Son()
{
cout<<"this is son()"<<endl;
}
void test_func_two()
{
cout<<"this is test_func_two"<<endl;
}
};
int main()
{
Father *p = new Son;
p->test_func_two();
delete p;
p = NULL;
return 0;
}
這里我定義了一個基類物件的指標,指向派生類物件,意圖去訪問派生類里面的函式,看一下編譯結果,
error: ‘class Father’ has no member named ‘test_func_two’; did you mean ‘test_func_one’?
p->test_func_two();
^~~~~~~~~~~~~
顯然,報錯了,不能訪問,驗證了剛剛的結論,
那么我如果非要訪問派生類物件怎么辦呢?
繼續修改代碼
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout<<"this is Father()"<<endl;
}
virtual void test_func_one()
{
cout<<"this is test_func_one";
}
};
class Son : public Father
{
public:
Son()
{
cout<<"this is son()"<<endl;
}
void test_func_one()
{
cout<<"this is test_func_two"<<endl;
}
};
int main()
{
Father *p = new Son;
p->test_func_one();
delete p;
p = NULL;
return 0;
}
編譯通過,看一下運行結果
this is Father()
this is son()
this is test_func_two
通過以上現象,不難發現,
基類物件的指標如果指向派生類物件,不能直接訪問派生類物件的屬性,如果要訪問,可以在基類里面定義虛函式,在派生類里對這個虛函式進行重新定義,就可以訪問派生類物件,
這種花里胡哨的用法,有沒有什么實際用途
我們可以通過基類來定義一個模板,派生類用來定義一些模板往上的東西,這么說可能有點抽象,舉個具體的例子,
比如我們要做攝像頭,不同型號的攝像頭可能具體實作的操作不太一樣,但是流程應該都差不多,所以可以在基類里面宣告一些Init,Start這類操作的虛函式作為模板,然后我們可以在派生類里針對具體的攝像頭型號來重新定義這些虛函式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/230344.html
標籤:其他
上一篇:基于STC89C52單片機的硬幣電子秤——2020科創杯
下一篇:cgb2008-京淘day09
