欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++學(xué)習(xí)之虛函數(shù)表與多態(tài)詳解

 更新時(shí)間:2023年03月31日 15:09:12   作者:寡人正在Coding  
這篇文章主要為大家詳細(xì)介紹了C++中虛函數(shù)表與多態(tài)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定的幫助,感興趣的小伙伴可以了解一下

概述

C++的多態(tài)在不同環(huán)境下實(shí)現(xiàn)方式可能不一樣,虛函數(shù)表是C++實(shí)現(xiàn)多態(tài)的一種方式。

問(wèn)題:

  • 什么情況下C++會(huì)使用虛指針和虛函數(shù)表?
  • 如果子類(lèi)不新增任何虛函數(shù),也不重寫(xiě)父類(lèi)的虛方法,會(huì)和父類(lèi)共用一張?zhí)摵瘮?shù)表么?
  • 父類(lèi)的構(gòu)造函數(shù)為什么不能正確的調(diào)用虛函數(shù)?

C++虛函數(shù)表指針和虛函數(shù)表

創(chuàng)建一個(gè)Base類(lèi)

class Base
{
public:
	int a;
	int b;
};

查看Base內(nèi)存布局

1>class Base size(8):
1> +---
1> 0 | a
1> 4 | b
1> +---

為Base類(lèi)添加一個(gè)虛函數(shù)

class Base
{
public:
	int a;
	int b;

	virtual void BaseFunc1()
	{
		std::cout << "Call BaseFunc1 From Base" << std::endl;
	};
};

此時(shí)再查看Base類(lèi)的內(nèi)存布局

1>class Base size(12):
1> +---
1> 0 | {vfptr}
1> 4 | a
1> 8 | b
1> +---
1>Base::$vftable@:
1> | &Base_meta
1> | 0
1> 0 | &Base::BaseFunc1
1>Base::BaseFunc1 this adjustor: 0

Base類(lèi)含有虛函數(shù)時(shí),.rodata只讀數(shù)據(jù)區(qū)會(huì)生成一個(gè)虛函數(shù)表,Base類(lèi)會(huì)生成一個(gè)指向該虛函數(shù)表的指針成員變量。虛函數(shù)表存放.text代碼區(qū)函數(shù)的地址。

再為Base添加一個(gè)虛函數(shù)

class Base
{
public:
	int a;
	int b;

	virtual void BaseFunc1()
	{
		std::cout << "Call BaseFunc1 From Base" << std::endl;
	};
	
	virtual void BaseFunc2()
	{
		std::cout << "Call BaseFunc2 From Base" << std::endl;
	}
};

查看Base類(lèi)的內(nèi)存分布

1>class Base size(12):
1> +---
1> 0 | {vfptr}
1> 4 | a
1> 8 | b
1> +---
1>Base::$vftable@:
1> | &Base_meta
1> | 0
1> 0 | &Base::BaseFunc1
1> 1 | &Base::BaseFunc2
1>Base::BaseFunc1 this adjustor: 0
1>Base::BaseFunc2 this adjustor: 0

Base類(lèi)的虛函數(shù)表增加了一個(gè)新函數(shù)地址。

C++ 虛函數(shù)表和多態(tài)

為Base創(chuàng)建一個(gè)派生類(lèi)Devire

class Derive : public Base
{
	//
};

查看Derive類(lèi)的內(nèi)存分布

1>class Derive size(12):
1> +---
1> 0 | +--- (base class Base)
1> 0 | | {vfptr}
1> 4 | | a
1> 8 | | b
1> | +---
1> +---
1>Derive::$vftable@:
1> | &Derive_meta
1> | 0
1> 0 | &Base::BaseFunc1
1> 1 | &Base::BaseFunc2

虛函數(shù)表的內(nèi)容和父類(lèi)Base一樣

查看Base和Derive的虛函數(shù)表地址

Base和Derive并非公用一張?zhí)摵瘮?shù)表。

Derive重寫(xiě)父類(lèi)Base的方法

class Derive : public Base
{
public:
	virtual void BaseFunc1() override
	{
		std::cout << "Call BaseFunc1 From Derive" << std::endl;
	}
};

查看Derive類(lèi)的內(nèi)存分布

1>class Derive size(12):
1> +---
1> 0 | +--- (base class Base)
1> 0 | | {vfptr}
1> 4 | | a
1> 8 | | b
1> | +---
1> +---
1>Derive::$vftable@:
1> | &Derive_meta
1> | 0
1> 0 | &Derive::BaseFunc1
1> 1 | &Base::BaseFunc2
1>Derive::BaseFunc1 this adjustor: 0

此時(shí)虛函數(shù)表的0元素被替換成了Derive::BaseFunc1的地址。

為Derive添加一個(gè)新的虛函數(shù)

class Derive : public Base
{
public:
	virtual void BaseFunc1() override
	{
		std::cout << "Call BaseFunc1 From Derive" << std::endl;
	}

	virtual void DeriveFunc1()
	{
		std::cout << "Call DeriveFunc1" << std::endl;
	}
};

再查看Derive類(lèi)的內(nèi)存分布

1>class Derive size(12):
1> +---
1> 0 | +--- (base class Base)
1> 0 | | {vfptr}
1> 4 | | a
1> 8 | | b
1> | +---
1> +---
1>Derive::$vftable@:
1> | &Derive_meta
1> | 0
1> 0 | &Derive::BaseFunc1
1> 1 | &Base::BaseFunc2
1> 2 | &Derive::DeriveFunc1
1>Derive::BaseFunc1 this adjustor: 0
1>Derive::DeriveFunc1 this adjustor: 0

Derive的虛函數(shù)表添加了一個(gè)新的函數(shù)地址。

讓父類(lèi)Base在構(gòu)造函數(shù)中調(diào)用虛函數(shù)BaseFunc1。

class Base
{
public:
	Base()
	{
		BaseFunc1();
	}
	int a;
	int b;

	virtual void BaseFunc1()
	{
		std::cout << "Call BaseFunc1 From Base" << std::endl;
	};

	virtual void BaseFunc2()
	{
		std::cout << "Call BaseFunc2 From Base" << std::endl;
	}
};

class Derive : public Base
{
public:
	virtual void BaseFunc1() override
	{
		std::cout << "Call BaseFunc1 From Derive" << std::endl;
	}

	virtual void DeriveFunc1()
	{
		std::cout << "Call DeriveFunc1" << std::endl;
	}
};

int main()
{
	Derive d;
	return 0;
}

輸出

Call BaseFunc1 From Base

虛函數(shù)的調(diào)用是錯(cuò)誤的。

查看Derive和Base的構(gòu)造函數(shù)的匯編代碼

Base 構(gòu)造函數(shù)匯編代碼

...
00641F4D mov dword ptr [eax],offset Base::`vftable' (0649B34h)
{
BaseFunc1();
00641F53 mov ecx,dword ptr [this]
00641F56 call Base::BaseFunc1 (0641488h)
}
00641F5B mov eax,dword ptr [this]
...

Derive 構(gòu)造函數(shù)的匯編代碼

...
0064220A mov ecx,dword ptr [this]
0064220D call Base::Base (06412B2h)
{
00642212 mov eax,dword ptr [this]
00642215 mov dword ptr [eax],offset Derive::`vftable' (0649B40h)
//
}
...

觀察匯編代碼可知,構(gòu)造Devire類(lèi)的對(duì)象時(shí),當(dāng)調(diào)用父類(lèi)Base的構(gòu)造函數(shù)時(shí),此時(shí)虛指針指向的虛函數(shù)表是父類(lèi)Base的,只有調(diào)用Derive自己的構(gòu)造函數(shù)時(shí),虛指針被賦值為Derive的虛函數(shù)表,所以父類(lèi)的構(gòu)造函數(shù)不能正確的調(diào)用虛函數(shù)。

以上就是C++學(xué)習(xí)之虛函數(shù)表與多態(tài)詳解的詳細(xì)內(nèi)容,更多關(guān)于C++虛函數(shù)表 多態(tài)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一篇文章帶你了解C語(yǔ)言二分查找

    一篇文章帶你了解C語(yǔ)言二分查找

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言二分查找法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C語(yǔ)言函數(shù)超詳細(xì)講解上篇

    C語(yǔ)言函數(shù)超詳細(xì)講解上篇

    函數(shù)是一組一起執(zhí)行一個(gè)任務(wù)的語(yǔ)句。每個(gè)?C?程序都至少有一個(gè)函數(shù),即主函數(shù)?main()?,所有簡(jiǎn)單的程序都可以定義其他額外的函數(shù),函數(shù)我們分兩篇來(lái)講解,接下來(lái)開(kāi)始第一篇
    2022-04-04
  • string,CString,char*之間的轉(zhuǎn)化

    string,CString,char*之間的轉(zhuǎn)化

    下面是MFC/C++/C中字符類(lèi)型CString, int, string, char*之間的轉(zhuǎn)換的說(shuō)明與舉例,經(jīng)常用的東西,相信對(duì)于用C/C++的朋友,還是比較有用的
    2013-03-03
  • C語(yǔ)言修煉之路一朝函數(shù)思習(xí)得?模塊思維世間生上篇

    C語(yǔ)言修煉之路一朝函數(shù)思習(xí)得?模塊思維世間生上篇

    函數(shù)是一組一起執(zhí)行一個(gè)任務(wù)的語(yǔ)句。每個(gè)?C?程序都至少有一個(gè)函數(shù),即主函數(shù)?main()?,所有簡(jiǎn)單的程序都可以定義其他額外的函數(shù)
    2022-03-03
  • C++?Qt開(kāi)發(fā)之關(guān)聯(lián)容器類(lèi)使用方法詳解

    C++?Qt開(kāi)發(fā)之關(guān)聯(lián)容器類(lèi)使用方法詳解

    當(dāng)我們談?wù)摼幊讨械臄?shù)據(jù)結(jié)構(gòu)時(shí),順序容器是不可忽視的一個(gè)重要概念,Qt?中提供了豐富的容器類(lèi),用于方便地管理和操作數(shù)據(jù),本章我們將主要學(xué)習(xí)關(guān)聯(lián)容器,主要包括?QMap?,QSet和?QHash,感興趣的朋友跟著小編一起來(lái)學(xué)習(xí)吧
    2023-12-12
  • 基于QT制作一個(gè)簡(jiǎn)易的傳輸文件小工具

    基于QT制作一個(gè)簡(jiǎn)易的傳輸文件小工具

    本文主要介紹了通過(guò)QT實(shí)現(xiàn)的一個(gè)文件傳輸小工具。功能就是能實(shí)現(xiàn)文件的雙向傳輸,即客戶(hù)端能傳給服務(wù)端,服務(wù)端可以傳給客戶(hù)端。文中示例代碼具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下
    2021-12-12
  • C++中設(shè)計(jì)一個(gè)類(lèi)時(shí)的注意事項(xiàng)分享

    C++中設(shè)計(jì)一個(gè)類(lèi)時(shí)的注意事項(xiàng)分享

    這篇文章主要來(lái)和大家分享一下C++中,設(shè)計(jì)一個(gè)類(lèi)要注意哪些東西,這往往也是C++面試時(shí)會(huì)考到的問(wèn)題,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • C++實(shí)現(xiàn)優(yōu)酷土豆去視頻廣告的方法

    C++實(shí)現(xiàn)優(yōu)酷土豆去視頻廣告的方法

    這篇文章主要介紹了C++實(shí)現(xiàn)優(yōu)酷土豆去視頻廣告的方法,實(shí)例分析了C++實(shí)現(xiàn)屏蔽功能的相關(guān)技巧,需要的朋友可以參考下
    2015-04-04
  • exit和atexit的區(qū)別詳細(xì)解析

    exit和atexit的區(qū)別詳細(xì)解析

    以下是對(duì)exit與atexit的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-09-09
  • C語(yǔ)言實(shí)現(xiàn)程序開(kāi)機(jī)自啟動(dòng)

    C語(yǔ)言實(shí)現(xiàn)程序開(kāi)機(jī)自啟動(dòng)

    本文給大家分享的是一則C語(yǔ)言實(shí)現(xiàn)開(kāi)機(jī)自啟動(dòng)的代碼,主要是通過(guò)C來(lái)獲取程序路徑修改注冊(cè)表項(xiàng)來(lái)實(shí)現(xiàn),有需要的小伙伴可以參考下
    2016-01-01

最新評(píng)論