最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++多態(tài)的全面講解

 更新時間:2022年06月06日 09:20:42   作者:林慢慢腦瓜子嗡嗡的  
多態(tài)按字面的意思就是多種形態(tài)。當類之間存在層次結(jié)構(gòu),并且類之間是通過繼承關(guān)聯(lián)時,就會用到多態(tài)。C++?多態(tài)意味著調(diào)用成員函數(shù)時,會根據(jù)調(diào)用函數(shù)的對象的類型來執(zhí)行不同的函數(shù)

1.多態(tài)的定義和實現(xiàn)

多態(tài)的淺層理解

多態(tài),即多種形態(tài),也就是說,不同的對象在完成某個行為時會產(chǎn)生不同的狀態(tài)。

舉個例子,買火車票時,普通人正常買票,學生半價買票,軍人優(yōu)先買票。

在C++中,多態(tài)就是對于同一個函數(shù),當調(diào)用的對象不同,他的操作也不同。

多態(tài)的構(gòu)成條件

多態(tài)是繼承體系中的一個行為,如果要在繼承體系中構(gòu)成多態(tài),需要滿足兩個條件:

1. 必須通過基類的指針或者引用調(diào)用虛函數(shù)

2. 被調(diào)用的函數(shù)必須是虛函數(shù),并且派生類必須要對繼承的基類的虛函數(shù)進行重寫

解釋1:因為子類和父類的虛表各自一份,倘若能夠通過對象傳遞的方式同時傳遞虛表的話,那么父類就可能拿到子類的虛表,不合理。

解釋2:有虛函數(shù)就有虛函數(shù)表,對象當中就會存放一個虛基表指針,通過虛基表指針指向的內(nèi)容來訪問對應(yīng)的函數(shù)。若子類沒有重寫父類的虛函數(shù)內(nèi)容,則子類也會調(diào)用父類的函數(shù)。

2.虛函數(shù)

虛函數(shù)就是被virtual修飾的類成員函數(shù)(這里的virtual和虛繼承的virtual雖然是同一個關(guān)鍵字,但是作用不一樣)

class Person
{
public:
	virtual void func()
	{
		cout << "普通人->正常買票" << endl;
	}
};

虛函數(shù)的重寫規(guī)則

虛函數(shù),即被virtual關(guān)鍵字重寫的類成員函數(shù)。

重寫(覆蓋):派生類中有一個跟基類中完全相同的虛函數(shù)(三同:即派生類虛函數(shù)與基類虛函數(shù)的返回值類型、函數(shù)名字、參數(shù)列表完全相同,也有例外!),這樣則稱子類重寫了父類的虛函數(shù)。

示例代碼如下:

class Person
{
public:
	virtual void func()
	{
		cout << "普通人->正常買票" << endl;
	}
};
class Student : public Person
{
public:
	//子類必須重寫父類的虛函數(shù)
	virtual void func()
	{
		cout << "學生->半價買票" << endl;
	}
};
//必須是父類的指針或引用去調(diào)用虛函數(shù)
//這里的參數(shù)類型不能是對象,否則是一份臨時拷貝,則無法構(gòu)成多態(tài)
void F(Person& ps)
{
	ps.func();
}
int main()
{
	Person ps;
	Student st;
	F(ps);
	F(st);
	return 0;
}

筆試選擇題??键c(選自Effective C++):

如果不滿足虛函數(shù)重寫的條件,例如參數(shù)不同則會變成重定義。

思考如下代碼輸出結(jié)果:

#include <iostream>
class Base{
public:
    virtual void Show(int n = 10)const{    //提供缺省參數(shù)值
        std::cout << "Base:" << n << std::endl;
    }
};
class Base1 : public Base{
public:
    virtual void Show(int n = 20)const{     //重新定義繼承而來的缺省參數(shù)值
        std::cout << "Base1:" << n << std::endl;
    }
};
int main(){
    Base* p1 = new Base1;        
    p1->Show();           
    return 0;
}

輸出的是Base1:10,

因為如果子類重寫了缺省值,此時的子類的缺省值是無效的,使用的還是父類的缺省值。原因是因為多態(tài)是動態(tài)綁定,而缺省值是靜態(tài)綁定。對于P1,他的靜態(tài)類型也就是這個指針的類型是Base,所以這里的缺省值是Base的缺省值,而動態(tài)類型也就是指向的對象是Base1,所以這里調(diào)用的虛函數(shù)則是Base1中的虛函數(shù),所以這里就是Base1中的虛函數(shù),Base中的缺省值,也就是Base1:10。

簡單概括就是:虛函數(shù)的重寫只重寫函數(shù)實現(xiàn),不重寫缺省值。

虛函數(shù)重寫條件的兩個例外

1.協(xié)變(返回值不同)

當基類和派生類的返回值類型不同時,如果基類對象返回基類對象的引用或者指針,派生類對象也返回的是派生類對象的引用或者指針時,就會引起協(xié)變。協(xié)變也能完成虛函數(shù)的重寫

例1:指針

class A {};
class B :public A {};
class Person
{
public:
	virtual A* func()
	{
		cout << "virtual A* func()" << endl;
		return new A;
	}
};
class Student : public Person
{
public:
	virtual B* func()
	{
		cout << "virtual B* func()" << endl;
		return new B;
	}
};

例2:引用

class Human
{
public:
	virtual Human& print()
	{
		cout << "i am a human" << endl;
		return *this;
	}
};
class Student : public Human
{
public:
	virtual Student& print()
	{
		cout << "i am a student" << endl;
		return *this;
	}
};

2.析構(gòu)函數(shù)的重寫(函數(shù)名不同)

析構(gòu)函數(shù)雖然函數(shù)名不同,但是也能構(gòu)成重寫,因為站在編譯器的視角,他所調(diào)用的析構(gòu)函數(shù)名稱都叫做destructor

為什么編譯器要通過這種方式讓析構(gòu)函數(shù)也能構(gòu)成重寫呢?

假設(shè)我用一個基類指針或者引用指向派生類對象,如果不構(gòu)成多態(tài)會怎樣?

class Human
{
public:
	~Human()
	{
		cout << "~Human()" << endl;
	}
};
class Student : public Human
{
public:
	~Student()
	{
		cout << "~Student()" << endl;
	}
};
int main()
{
	Human* h = new Student;
	delete h;
	return 0;
}

上述代碼只會調(diào)用Human的析構(gòu)函數(shù),即如果不構(gòu)成多態(tài),那么指針是什么類型的,就會調(diào)用什么類型的析構(gòu)函數(shù),這也就導致了一種情況,如果派生類的析構(gòu)函數(shù)中有資源釋放,而這里卻沒有釋放掉那些資源,就會導致內(nèi)存泄漏的問題。

所以為了防止這種情況,必須要將析構(gòu)函數(shù)定義為虛函數(shù)。這也就是編譯器將析構(gòu)函數(shù)重命名為destructor的原因

class Human
{
public:
	virtual ~Human()
	{
		cout << "~Human()" << endl;
	}
};
class Student : public Human
{
public:
	virtual ~Student()
	{
		cout << "~Student()" << endl;
	}
};
int main()
{
	Human* h = new Student;
	delete h;
	return 0;
}

3.C++11 override 和 final

override

override關(guān)鍵字是用來檢測派生類虛函數(shù)是否構(gòu)成重寫的關(guān)鍵字。

如基類虛函數(shù)沒有virtual或者派生類虛函數(shù)名拼錯等問題,這些問題不會被編譯器檢查出來,發(fā)生錯誤時也很難一下子鎖定,所以C++增添了override這一層保險,當修飾的虛函數(shù)不構(gòu)成重寫時就會編譯錯誤。

class A
{
public:
	virtual void func() {}
};
class B : public A
{
public:
	//未重寫則報錯
	virtual void func() override {};
};

final

使用final修飾的虛函數(shù)不能被重寫。

如果某一個虛函數(shù)不想被派生類重寫,就可以用final來修飾這個虛函數(shù)

class Human
{
public:
	virtual void print() final
	{
		cout << "i am a human" << endl;
	}
};
class Student : public Human
{
public:
	virtual void print()
	{
		cout << "i am a student" << endl;
	}
};

重載對比重定義(隱藏)與重寫(覆蓋)

4.抽象類

虛函數(shù)后面加上=0就是純虛函數(shù),包含純虛函數(shù)的類即為抽象類(接口類)。抽象類不能實例化出對象,派生類繼承抽象類后若沒有重寫純虛函數(shù)那么仍為抽象類,亦不能實例化出對象。純虛函數(shù)規(guī)范了派生類必須重寫虛函數(shù),并且更加體現(xiàn)出了接口繼承。

抽象類就像是一個藍圖,為派生類描述好一個大概的架構(gòu),派生類必須實現(xiàn)完這些架構(gòu),至于要在這些架構(gòu)上面做些什么,增加什么,就屬于派生類自己的問題。

class Human
{
public:
	virtual void print() = 0;
};
class Student : public Human
{
public:
	virtual void print()
	{
		cout << "i am a student" << endl;
	}
};
class Teacher : public Human
{
public:
	virtual void print()
	{
		cout << "i am a teacher" << endl;
	}
};

接口繼承與實現(xiàn)繼承

普通函數(shù)的繼承就是接口繼承,派生類可以使用基類的函數(shù);而虛函數(shù)的重寫則是實現(xiàn)繼承,派生類繼承的僅僅是基類的函數(shù)接口,目的是為了重寫基類虛函數(shù)的函數(shù)體,達成多態(tài)。因此如果不實現(xiàn)多態(tài),則不要將函數(shù)定義為虛函數(shù)。

到此這篇關(guān)于C++多態(tài)的全面講解的文章就介紹到這了,更多相關(guān)C++多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言每日練習之求兩個矩陣的乘積詳解

    C語言每日練習之求兩個矩陣的乘積詳解

    這篇文章主要介紹了如何求兩個矩陣的乘積,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-11-11
  • C++實現(xiàn)學生考勤信息管理系統(tǒng)

    C++實現(xiàn)學生考勤信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)學生考勤信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C++實現(xiàn)俄羅斯方塊游戲

    C++實現(xiàn)俄羅斯方塊游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)俄羅斯方塊游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • 如何在C++中通過模板去除強制轉(zhuǎn)換

    如何在C++中通過模板去除強制轉(zhuǎn)換

    本文講解的是如何在C++中通過模板去除強制轉(zhuǎn)換,在編程工作中應(yīng)盡量少使用強制類型轉(zhuǎn)換,模板有助于我們實現(xiàn)這一目的,需要的朋友可以參考下
    2015-07-07
  • dev-c++創(chuàng)建lib(靜態(tài)鏈接庫)文件的實現(xiàn)步驟

    dev-c++創(chuàng)建lib(靜態(tài)鏈接庫)文件的實現(xiàn)步驟

    本文主要介紹了dev-c++創(chuàng)建lib(靜態(tài)鏈接庫)文件的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • C++動態(tài)內(nèi)存分配(new/new[]和delete/delete[])詳解

    C++動態(tài)內(nèi)存分配(new/new[]和delete/delete[])詳解

    這篇文章主要介紹了C++動態(tài)內(nèi)存分配(new/new[]和delete/delete[])詳解的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++中vector迭代器失效問題的原因及解決方案

    C++中vector迭代器失效問題的原因及解決方案

    迭代器(iterator)是一種用于遍歷數(shù)據(jù)集合的的對象,它提供了一種訪問數(shù)據(jù)集合中元素的方式,而無需暴露數(shù)據(jù)集合內(nèi)部的細節(jié),使用迭代器,我們可以對數(shù)據(jù)集合中的每個元素進行處理,本文介紹了C++中關(guān)于vector迭代器失效問題的原因及解決方案,需要的朋友可以參考下
    2024-09-09
  • C++類中三大函數(shù)詳解(構(gòu)造、析構(gòu)和拷貝)

    C++類中三大函數(shù)詳解(構(gòu)造、析構(gòu)和拷貝)

    c++三大函數(shù)指的是拷貝構(gòu)造、拷貝賦值、析構(gòu)函數(shù),下面這篇文章主要給大家介紹了關(guān)于C++類中三大函數(shù)(構(gòu)造、析構(gòu)和拷貝)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • C++中std::vector的具體使用

    C++中std::vector的具體使用

    C++標準庫中的std::vector是一種動態(tài)數(shù)組容器,適用于算法競賽中的動態(tài)數(shù)據(jù)存儲、數(shù)組擴展和模擬棧/二維數(shù)組等場景,本文就來介紹一下,感興趣的可以了解一下
    2025-02-02
  • C++對象的動態(tài)建立與釋放詳解

    C++對象的動態(tài)建立與釋放詳解

    我們知道可以用new運算符可以動態(tài)的分配內(nèi)存,用delete運算符可以釋放這些內(nèi)存。當我們使用new運算符動態(tài)的分配一個內(nèi)存之后,會自動返回一個該內(nèi)存段的起始地址,也就是指針。
    2013-10-10

最新評論

保康县| 西昌市| 黄浦区| 武安市| 昔阳县| 锡林浩特市| 清镇市| 嘉黎县| 得荣县| 甘孜县| 长沙县| 固始县| 密山市| 云梦县| 襄垣县| 香港| 永顺县| 三门峡市| 鲁甸县| 宜昌市| 额济纳旗| 南开区| 阳东县| 衡阳市| 钟祥市| 轮台县| 聂荣县| 阿拉善左旗| 青浦区| 江口县| 海安县| 潮州市| 麦盖提县| 南木林县| 象山县| 西昌市| 屏东市| 玉山县| 从江县| 育儿| 石狮市|