国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

波奇學(xué)C++:多態(tài)知識點

這篇具有很好參考價值的文章主要介紹了波奇學(xué)C++:多態(tài)知識點。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

多態(tài)中函數(shù)的重寫(基類指針訪問派生類函數(shù)),只重寫函數(shù)的實現(xiàn),而不重寫聲明。

class Person
{
public:
	 virtual void fun(int i = 0)
	{
		cout << "Person"<<" "<<i;
	}
};
class Student:public Person
{
public:
	 virtual void fun(int i = 1)
	{
		cout << "student" <<" "<<i;
	}
};
int main()
{
	Person p;
	Student st;
	Person* pp = &st;
	pp->fun();

	return 0;
}

結(jié)果是 student 0 原因在于重寫時只重寫函數(shù)的實現(xiàn),就是說相當于Person的fun的聲明和Student的函數(shù)實現(xiàn)的拼在一起所以缺省值是0。

為什么多態(tài)調(diào)用(重寫)只能用父類的指針和引用,不能子類指針或者引用,不能是父類對象?

如果是子類指針或者引用就不是多態(tài)調(diào)用了只是單存子類對父類的重定義,隱藏函數(shù)。

上一篇文章提到的,多態(tài)的本質(zhì)就是基類和派生類的虛表中保存的虛函數(shù)地址被覆蓋了,多態(tài)調(diào)用意味著訪問的必須是子類的虛表而不是父類的。

子類對象直接賦值父類不會拷貝虛表虛函數(shù)的地址

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

上圖為賦值前,下圖為賦值后,如圖他們的__vfptr始終不同,所以父類對象必然無法訪問子類對象的虛函數(shù)的地址。

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

為什么指針和引用可以?

父類型指針表示它范圍的范圍是父類,所以它指向子對象時,本質(zhì)上依然說訪問子類的父類部分,虛表依然是子類的虛表。

引用同理,相當于切割出子類中父類的部分。本質(zhì)上依然是子類的虛表。

為什么父類指針可以指向子類對象?可以指向意味著結(jié)構(gòu)相似,原因在于,繼承相當于把父對象一整個拷貝放在子對象中,結(jié)構(gòu)相似也是向上轉(zhuǎn)換的基礎(chǔ)

虛表的存儲在代碼段

證明思路:輸出各個區(qū)的地址和虛表的地址,進行比較,字節(jié)相差較少說明在哪個區(qū)。

int main()
{
	Person p;
	Student st;
	int a = 1;
	printf("棧上:%x\n", &a);
	int* b = new int;
	printf("堆上:%x\n", b);
	static int c = 0;
	printf("靜態(tài)區(qū):%x\n", &c);
	const char* d = "abcde";
	printf("代碼段:%x\n", d);
	printf("虛表1:%x\n", *((int*)&p));
	printf("虛表2:%x\n", *((int*)&st));
	return 0;

}

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

注意打印對象是打印對象的成員變量的值,這里是因為__vptr內(nèi)置變量(保存虛表地址)的在成員變量首位,所以可以打印出來,同時int* 是只取虛表的地址后四個字節(jié)(小端機),%x也是只打印地址的后4位字節(jié)。

通過比較可發(fā)現(xiàn),虛表和代碼段的位置更近,所以虛表在代碼段中。

派生類新的虛函數(shù)保存在虛表中,原有虛函數(shù)的地址的下面

class Person
{
public:
	 virtual void fun(int i = 0)
	{
		cout << "Person"<<" "<<i;
	}
	 int _a;
};
class Student:public Person
{
public:
	 virtual void fun(int i = 1)
	{
		cout << "student" <<" "<<i;
	}
	 virtual void fun1()
	 {
		 cout << "new virtual fun1()";
	 }
	 int _b;
};

fun1()是Student的虛函數(shù),fun1保存在子函數(shù)的虛表中

證明:虛表保存函數(shù)指針地址,虛表可以看成指針數(shù)組,所以我們可以把虛表的函數(shù)指針打印出來。

typedef void(*FUNC_PTR) ();//重定義函數(shù)指針類型
//形參是數(shù)組,實參為數(shù)組指針
void PrintVFT(FUNC_PTR table[])
{
    //vs會在虛表末尾保存一個空指針,所以循環(huán)到nullptr為止
	for (size_t i = 0; table[i] != nullptr; i++)
	{
		printf("[%d]:%p\n", i, table[i]);
	}
}
int main()
{
	Person ps;
	Student st;
	int vft1 = *((int*)&ps);
//86位機器地址是32位轉(zhuǎn)換成int*
	PrintVFT((FUNC_PTR*)vft1);
	int vft2 = *((int*)&st);
	PrintVFT((FUNC_PTR*)vft2);
	return 0;
}

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

?如圖上面為父類虛表保存的地址,下面為派生類虛表保存的指針地址。重寫的虛函數(shù)覆蓋了原有的地址,并且新地址在虛表內(nèi)。

靜態(tài)多態(tài):指的是函數(shù)重載,指的是編譯的時候函數(shù)地址確定了

動態(tài)多態(tài):繼承,虛函數(shù)重寫,調(diào)用的函數(shù)地址的確定是在運行時去虛表中確定的

多繼承的多態(tài)問題

typedef void(*FUNC_PTR) ();
void PrintVFT(FUNC_PTR table[])
{
	for (size_t i = 0; table[i] != nullptr; i++)
	{
		printf("[%d]:%p", i, table[i]);
		FUNC_PTR f = table[i];
		f();
		printf("\n");
	}
}
class Base1 {
public:
	virtual void func1() { cout << "Base1::func1" << endl; }
	virtual void func2() { cout << "Base1::func2" << endl; }
private:
	int b1;
};
class Base2 {
public:
	virtual void func1() {
		cout << "Base2::func1" << endl;
	}
	virtual void func2() { cout << "Base2::func2" << endl; }
private:
	int b2;
};
class Derive :public Base1, public Base2
{
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
private:
	int d1;
};
int main()
{
	Derive d;
	cout << sizeof(d) << endl;
	int vft1 = *((int*)&d);
	Base2* ptr = &d;
	int vft2 = *((int*)ptr);
	PrintVFT((FUNC_PTR*)vft1);
	PrintVFT((FUNC_PTR*)vft2);
	return 0;

}

下面代碼的Derive繼承了Base1和Base2,其中兩個fun1()都被繼承了。

打印結(jié)果

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

?為什么是20?

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

?因為是一整個對象繼承,所以會存在兩個虛表,base1,base2虛表指針+int變量 8+8+4=20

由上面的結(jié)果圖可知fun1在兩個虛表中被重寫,且都調(diào)用了同一個函數(shù)。但是地址卻不一樣,

實際上調(diào)用虛表2的fun()的地址,會改變指針位置和虛表1fun()指針相同,再調(diào)用函數(shù)。

反匯編證明

b1,b2指針分別調(diào)用fun1(),反匯編,call指令進入func1函數(shù),此時

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

注意此處fun1()的地址是0C92840h

調(diào)用base2的fun1虛表地址,此時地址是0C94670h

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

進入call指令,ecx-8,再jump向0C91244h地址最后到base1虛表的地址。

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++?

波奇學(xué)C++:多態(tài)知識點,波奇學(xué)c,c++

?簡單來說指向base2部分的指針,先指向base1的,再調(diào)用指針1保存的重寫函數(shù)的地址。文章來源地址http://www.zghlxwxcb.cn/news/detail-707318.html

到了這里,關(guān)于波奇學(xué)C++:多態(tài)知識點的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • C++基礎(chǔ)知識點整理筆記(四)

    10. C++的內(nèi)存管理 在C++中,內(nèi)存被分成五個區(qū):棧、堆、自由存儲區(qū)、靜態(tài)存儲區(qū)、常量區(qū) (一) 棧:存放函數(shù)的參數(shù)和局部變量,編譯器自動分配和釋放 (二) 堆:new動態(tài)分配的內(nèi)存,由程序員手動進行釋放,否則程序結(jié)束后,由操作系統(tǒng)自動進行回收 (三) 自由存儲區(qū)

    2024年02月15日
    瀏覽(31)
  • C++筆記(細碎小知識點)1

    2024年02月08日
    瀏覽(23)
  • C++進行3D建模學(xué)習哪些知識點?

    1. C++語言基礎(chǔ): 學(xué)習C++的基本語法、數(shù)據(jù)類型、控制流、函數(shù)等基礎(chǔ)知識。 了解C++的面向?qū)ο缶幊蹋∣OP)概念和相關(guān)特性,如類、繼承、多態(tài)等。 2. 數(shù)學(xué)和幾何知識: 3D建模涉及到數(shù)學(xué)和幾何的概念。 你需要了解向量、矩陣、坐標系轉(zhuǎn)換、點、線、面、多邊形等基本幾何概

    2024年02月07日
    瀏覽(30)
  • QT C++ 中的重要知識點

    以下是一些 QT C++ 中的重要知識點: 1. 信號和槽機制 :QT C++ 中的信號和槽機制是一種事件處理機制,用于在對象之間傳遞消息。信號是一種特殊的函數(shù),當特定事件發(fā)生時,它們被發(fā)射。槽是一種普通的函數(shù),用于響應(yīng)信號。通過連接信號和槽,可以實現(xiàn)對象之間的通信。

    2024年02月05日
    瀏覽(20)
  • 面試指南:C++之STL知識點

    相關(guān)系列文章 面試指南:C++之STL知識點 C++內(nèi)存分配策略 深入理解STL空間分配器(一): new_allocator 深入理解STL空間分配器(二):mt_allocator 深入理解STL空間分配器(三):pool_allocator 深入理解STL空間分配器(四):bitmap_allocator 目錄 1.講講STL的六大組件 2.vector 2.1.簡單說說vector 2.2.vecto

    2024年02月21日
    瀏覽(22)
  • 【C++】學(xué)習C++時,經(jīng)常忘記的知識點合集(1)

    不清楚的知識點合集:C++篇 參考答案:chatgpt。有 些答案不保證正確 目前使用最廣泛的C++標準是C++17。C++17于2017年發(fā)布,引入了許多新的語言特性和庫功能,包括結(jié)構(gòu)化綁定、constexpr if、折疊表達式、變量模板、并行STL算法等等。同時,C++17還對一些現(xiàn)有特性進行了改進和擴

    2024年02月08日
    瀏覽(27)
  • C++入門知識點——解決C語言不足

    C++入門知識點——解決C語言不足

    ????????????????????????Take your time ! ???????????????????????? ??個人主頁:??????大魔王?????? ??所屬專欄:??魔王的修煉之路–C++?? 如果你覺得這篇文章對你有幫助,請在文章結(jié)尾處留下你的 點贊 ??和 關(guān)注 ??,支持一下博主

    2024年02月12日
    瀏覽(22)
  • 【C++】——C++基礎(chǔ)知識點(C++和C語言的區(qū)別)

    【C++】——C++基礎(chǔ)知識點(C++和C語言的區(qū)別)

    C++是在C的基礎(chǔ)之上,容納進去了面向?qū)ο缶幊趟枷?,并增加了許多有用的庫,以及編程范式 等。熟悉C語言之后,對C++學(xué)習有一定的幫助。 本博客目標: 1.補充C語言語法的不足,以及C++是如何對C語言設(shè)計不合理的地方進行優(yōu)化的,比如:作用域方面、IO方面、函數(shù)方面、指

    2024年02月03日
    瀏覽(25)
  • C++ Primer 6.2參數(shù)傳遞 知識點+練習題

    C++ Primer 6.2參數(shù)傳遞 知識點+練習題

    以上需要傳入string可能很大,不適合用值傳遞,拷貝耗空間 不需要修改,最好用const 底層const:指向的對象是一個常量, 不允許用指針修改 頂層const:只允許指向一個對象 P57 有時間詳細整理 不用const限制傳入實參范圍 記住, 多維數(shù)組就是數(shù)組的數(shù)組 若為2維數(shù)組,傳入數(shù)組

    2024年02月02日
    瀏覽(32)
  • 哈希表C++哈希表詳解(知識點+相關(guān)LeetCode題目)

    目錄 前言 一、什么是哈希表 二、哈希表的操作 2.1 操作時間復(fù)雜度 2.2 哈希表通用API 2.3 建立哈希表 2.3 哈希表常見結(jié)構(gòu)介紹 Set(集合) Map(映射) unordered_map(哈希表) 三、哈希表的力扣經(jīng)典題目 有效的字母異位詞242 兩個數(shù)組的交集 349 兩數(shù)之和1 四數(shù)相加II 454 三數(shù)之和

    2024年03月20日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包