C+繼承之同名覆蓋,函數(shù)重寫與多態(tài)詳解
如果父類成員和子類成員名字相同是否允許?會(huì)發(fā)生什么?
同名覆蓋
#include<iostream>
using namespace std;
class Base
{
public:
int m_data;
Base():m_data(1)//父類初始化為1
{ }
};
class Derived : public Base
{
public:
int m_data;
Derived():m_data(2)//子類初始化為2
{ }
};
int main()
{
Derived d;
//父類的m_data被隱藏了,但仍存在,可以通過::符訪問
cout<<"base data: "<<d.Base::m_data<<endl;
//直接訪問m_data得到的是子類成員的值
cout<<"derived data: "<<d.m_data<<endl;
//驗(yàn)證兩個(gè)int剛好是8字節(jié),說明d對(duì)象有兩個(gè)整型數(shù)
cout<<sizeof(d)<<endl;
return 0;
}
運(yùn)行結(jié)果
base data: 1
derived data: 2
8
說明父類和子類是允許存在同名成員的,只不過父類的成員被編譯器隱藏了,正常訪問得到的是子類成員的值。
那么如果是函數(shù)同名呢?
函數(shù)重寫
函數(shù)重寫是同名覆蓋的一種特殊情況,即子類中重新實(shí)現(xiàn)父類中的同名函數(shù),屬于同名覆蓋
#include<iostream>
using namespace std;
class Base
{
public:
void print()
{
cout<<"Base class"<<endl;
}
};
class Derived : public Base
{
public:
void print()
{
cout<<"Derived class"<<endl;
}
};
int main()
{
Derived d;
d.Base::print();//父類函數(shù)被隱藏
d.print();
return 0;
}
運(yùn)行結(jié)果
Base class
Derived class
如果調(diào)用how_to_print函數(shù),期望傳入父類對(duì)象時(shí)調(diào)用父類打印函數(shù),傳入子類對(duì)象時(shí)調(diào)用子類對(duì)象函數(shù)
void how_to_print(Base* p)
{
p->print();//期望根據(jù)對(duì)象選擇相應(yīng)函數(shù),不能實(shí)現(xiàn)
}
int main()
{
Base b;
Derived d;
how_to_print(&b);
how_to_print(&d);
return 0;
}
結(jié)果卻是都打印Base class
Base class
Base class
結(jié)果沒有符合預(yù)期,分析:
1.傳入父類對(duì)象b的地址時(shí),父類指針指向父類對(duì)象,打印正常;
2.傳入子類對(duì)象d的地址時(shí),父類指針指向子類對(duì)象,此時(shí)由于賦值兼容性(子類對(duì)象可以當(dāng)作父類對(duì)象使用),子類對(duì)象退化為父類對(duì)象(父類指針只能訪問父類成員),編譯器認(rèn)為父類指針指向的是父類對(duì)象,因此最終調(diào)用了父類的打印函數(shù)
以上結(jié)果是合理的,卻沒有符合預(yù)期的目的,這也是函數(shù)重寫帶來的問題。如果不能實(shí)現(xiàn)以上目的,函數(shù)重寫是沒有意義的,那么如何實(shí)現(xiàn)父類指針(引用)指向:
- 父類對(duì)象,調(diào)用父類函數(shù)
- 子類對(duì)象,調(diào)用重寫函數(shù)
實(shí)際上以上行為就是多態(tài)
多態(tài)
所謂多態(tài),即同樣的調(diào)用語句,在實(shí)際運(yùn)行時(shí)存在不同的表現(xiàn)狀態(tài),依據(jù)則是對(duì)象的類型不同
要實(shí)現(xiàn)上文中函數(shù)重寫的多態(tài),需要引入virtual關(guān)鍵字,C++原生支持多態(tài)
- 通過使用virtual關(guān)鍵字對(duì)多態(tài)進(jìn)行支持
- 被virtual聲明的函數(shù)被重寫后具有多態(tài)特性
- 被virtual聲明的函數(shù)叫做虛函數(shù)
在父類函數(shù)print聲明前添加virtual關(guān)鍵字,print函數(shù)成為虛函數(shù),子類重寫的函數(shù)也將自動(dòng)變成虛函數(shù),這樣就可以實(shí)現(xiàn)多態(tài)
class Base
{
public:
virtual void print()//加virtual變成了虛函數(shù)
{
cout<<"Base class"<<endl;
}
};
運(yùn)行結(jié)果
Base class
Derived class
多態(tài)的意義:
在程序運(yùn)行過程中展現(xiàn)出動(dòng)態(tài)的特性函數(shù)重寫必須多態(tài)實(shí)現(xiàn),否則沒有意義多態(tài)是面向?qū)ο蠼M件化程序設(shè)計(jì)的基礎(chǔ)特性
總結(jié)
同名覆蓋是繼承時(shí)發(fā)生在父類和子類之間,子類同名成員覆蓋(屏蔽)父類同名成員的現(xiàn)象;函數(shù)重寫也是同名覆蓋,函數(shù)重寫多態(tài)實(shí)現(xiàn)才有意義,C++通過virtual支持多態(tài)多態(tài)是面向?qū)ο蠼M件化程序設(shè)計(jì)的基礎(chǔ)特性
相關(guān)文章
C++?數(shù)據(jù)結(jié)構(gòu)超詳細(xì)講解單鏈表
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之單鏈表,鏈表是由一個(gè)個(gè)結(jié)點(diǎn)鏈結(jié)成的。結(jié)點(diǎn)包括數(shù)據(jù)域和指針域兩部分,數(shù)據(jù)域用來存儲(chǔ)數(shù)據(jù)元素的信息,指針域用來存儲(chǔ)下一個(gè)結(jié)點(diǎn)的地址,更詳細(xì)內(nèi)容請(qǐng)需要的小伙伴參考下面文章內(nèi)容2022-03-03
C++實(shí)現(xiàn)宿舍管理查詢系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)宿舍管理查詢系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
詳解C++程序中定義struct結(jié)構(gòu)體的方法
C++中同樣擁有C語言中的結(jié)構(gòu)體,下面就來詳解C++程序中定義struct結(jié)構(gòu)體的方法,需要的朋友可以參考下2016-05-05

