C++知識點--多態(tài)-創(chuàng)新互聯(lián)

C++知識點 – 多態(tài)

河西ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!文章目錄
  • C++知識點 -- 多態(tài)
  • 一、多態(tài)概念
    • 1.概念
  • 二、多態(tài)的定義及實現(xiàn)
    • 1、多態(tài)的構(gòu)成條件
    • 2、虛函數(shù)
    • 3、虛函數(shù)的重寫
    • 4.虛函數(shù)重寫的特例
    • 5、不符合多態(tài)的場景
    • 6、C++11的override和final
    • 7、重載、覆蓋(重寫)、隱藏(重定義)的對比
    • 8、例題
  • 三、抽象類
  • 四、多態(tài)的原理
    • 1、虛函數(shù)表
    • 2、多態(tài)的原理
  • 五、單繼承和多繼承關(guān)系的虛函數(shù)表
    • 1、單繼承中的虛表
    • 2、多繼承中的虛表
  • 六、多態(tài)常見面試問題
    • 1.例題
    • 2.inline函數(shù)可以是虛函數(shù)嗎
    • 3.靜態(tài)成員函數(shù)可以是虛函數(shù)嗎
    • 4.構(gòu)造函數(shù)可以是虛函數(shù)嗎
    • 5.析構(gòu)函數(shù)可以是虛函數(shù)嗎
    • 6.拷貝構(gòu)造和賦值可以是虛函數(shù)嗎
    • 7.對象訪問普通函數(shù)快還是虛函數(shù)快
    • 8.虛函數(shù)表是在什么階段生成的,存在哪里


一、多態(tài)概念 1.概念

多態(tài)就是完成某個行為時,不同對象去完成時會產(chǎn)生不同的狀態(tài)。
比如買票,普通人買全價票,學(xué)生買半價票,軍人優(yōu)先買票。

二、多態(tài)的定義及實現(xiàn) 1、多態(tài)的構(gòu)成條件

多態(tài)是在不同繼承關(guān)系的類對象,去調(diào)用同一函數(shù),產(chǎn)生不同的行為。
繼承中構(gòu)成多態(tài)還有兩個條件:
1.必須通過基類的指針或引用去調(diào)用虛函數(shù);
2.被調(diào)用的函數(shù)必須是虛函數(shù),且派生類必須對基類的虛函數(shù)進(jìn)行重寫;

2、虛函數(shù)

用virtual關(guān)鍵字修飾的成員函數(shù)就是虛函數(shù)。
代碼如下:

class Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 全價"<< endl;
	}
};
3、虛函數(shù)的重寫

派生類中的虛函數(shù)構(gòu)成重寫(覆蓋)的條件有:函數(shù)名、參數(shù)和返回值類型相同,但是函數(shù)的實現(xiàn)不同;
如果不構(gòu)成重寫,就是隱藏關(guān)系;
代碼如下:

class Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 半價"<< endl;      //重寫
	}
};

class Soldier : public Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 優(yōu)先"<< endl;      //重寫
	}
};

void Func(Person& p)           //使用父類的引用調(diào)用虛函數(shù)
{p.BuyTicket();
}

void Test()
{Person p;
	Func(p);

	Student st;
	Func(st);

	Soldier sd;
	Func(sd);
}

以上代碼就完整的構(gòu)成了多態(tài),其運行效果為:
在這里插入圖片描述
不同的對象調(diào)用同一個虛函數(shù),呈現(xiàn)出了不同的效果。

4.虛函數(shù)重寫的特例

1.將子類中虛函數(shù)的virtual去掉

class Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	void BuyTicket()
	{cout<< "買票 - 半價"<< endl;
	}
};

這樣依然構(gòu)成重寫,子類中依然是虛函數(shù),編譯器認(rèn)為先把父類的虛函數(shù)繼承下來了,而且是接口繼承,將函數(shù)接口完整繼承下來了,子類中只是將函數(shù)的實現(xiàn)進(jìn)行重寫。

2.重寫的協(xié)變
返回值類型可以不同,要求必須是父子關(guān)系的指針或引用;
代碼如下:

class Person
{public:
	virtual Person* BuyTicket()
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 半價"<< endl;
	}
};

以上的代碼是會報錯的,因為只滿足了返回值類型不同,并不是父子關(guān)系的指針或引用,下面的代碼才是協(xié)變:

class Person
{public:
	virtual Person* BuyTicket()
	{cout<< "買票 - 全價"<< endl;
		return this;
	}
};

class Student : public Person
{public:
	virtual Student* BuyTicket()       //返回值是有父子關(guān)系的指針或引用
	{cout<< "買票 - 半價"<< endl;
		return this;
	}
};

運行結(jié)果為:
在這里插入圖片描述
上面的代碼依然能夠構(gòu)成多態(tài)。

3.析構(gòu)函數(shù)的重寫
建議在繼承中將析構(gòu)函數(shù)定義為虛函數(shù);

class Person
{public:
	virtual ~Person()
	{cout<< "~Person()"<< endl;
	}
};

class Student : public Person
{public:
	virtual ~Student()      //子類的析構(gòu)函數(shù)與父類的析構(gòu)函數(shù)的函數(shù)名并不相同
	{cout<< "~Student()"<< endl;
	}
};
int main()
{Person* p1 = new Person;
	delete p1;

	Person* p2 = new Student;//父類指針指向子類對象,符合多態(tài)調(diào)用
	delete p2;
	
	return 0;
}

以上代碼的運行結(jié)果為:
在這里插入圖片描述
子類和父類的析構(gòu)函數(shù),參數(shù)類型和返回值類型都相同,編譯器為了讓他們構(gòu)成重寫,將析構(gòu)函數(shù)名改寫為destructor,所以,上述代碼中析構(gòu)函數(shù)完成了重寫。
只有子類析構(gòu)函數(shù)重寫了父類的析構(gòu)函數(shù),這里才能正確調(diào)用,指針指向父類對象,調(diào)用父類的析構(gòu)函數(shù),指向子類對象就調(diào)用子類的析構(gòu)函數(shù)。

如果析構(gòu)函數(shù)不是虛函數(shù):

class Person
{public:
	~Person()
	{cout<< "~Person()"<< endl;
	}
};

class Student : public Person
{public:
	~Student()      //子類的析構(gòu)函數(shù)與父類的析構(gòu)函數(shù)的函數(shù)名并不相同
	{cout<< "~Student()"<< endl;
	}
};
int main()
{Person* ptr1 = new Person;
	delete ptr1;

	Person* ptr2 = new Student;//父類指針指向子類對象,符合多態(tài)調(diào)用
	delete ptr2;
	
	return 0;
}

在這里插入圖片描述
在子類delete時,調(diào)用的還是父類的析構(gòu)函數(shù):
在這里插入圖片描述
這里是普通調(diào)用,不符合多態(tài),在編譯時就決定了;
ptr2是Person*類型的指針,call的是Person的析構(gòu)函數(shù);
ptr1希望調(diào)用父類的析構(gòu),ptr2希望調(diào)用子類的析構(gòu),所以把析構(gòu)設(shè)計成符合多態(tài)的函數(shù)名。

5、不符合多態(tài)的場景

1.不是父類的指針或引用調(diào)用虛函數(shù)
代碼如下:

class Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 半價"<< endl;
	}
};

void Func(Person p)
{p.BuyTicket();
}

運行結(jié)果為:
在這里插入圖片描述
上述代碼是不構(gòu)成多態(tài)的。

2.不符合虛函數(shù)重寫
2.1將父類虛函數(shù)的virtual去掉

class Person
{public:
	void BuyTicket()
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 半價"<< endl;
	}
};

void Func(Person& p)
{p.BuyTicket();
}

運行結(jié)果為:
在這里插入圖片描述
是不符合虛函數(shù)重寫的,自然就不構(gòu)成多態(tài)。

2.2參數(shù)類型不同

class Person
{public:
	void BuyTicket(char)
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket(int)
	{cout<< "買票 - 半價"<< endl;
	}
};

void Func(Person& p)
{p.BuyTicket();
}

運行結(jié)果為:
在這里插入圖片描述
同樣不符合多態(tài)。

6、C++11的override和final

1.final:修飾虛函數(shù),表示其不能再被重寫(用的很少)

class Person
{public:
	virtual void BuyTicket() final
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket()
	{cout<< "買票 - 半價"<< endl;
	}
};

編譯之后會報錯:
在這里插入圖片描述
2.override:檢查派生類虛函數(shù)是否重寫了某個基類的虛函數(shù),若沒有重寫編譯報錯(常用)

class Person
{public:
	virtual void BuyTicket(int)
	{cout<< "買票 - 全價"<< endl;
	}
};

class Student : public Person
{public:
	virtual void BuyTicket(char) override//參數(shù)類型不一致,未完成重寫
	{cout<< "買票 - 全價"<< endl;
	}
};

上述代碼子類的虛函數(shù)未完成重寫,在后面加了override后,編譯器就會報錯:
在這里插入圖片描述
override常用于檢查子類虛函數(shù)重寫的語法是否正確。

7、重載、覆蓋(重寫)、隱藏(重定義)的對比

在這里插入圖片描述

8、例題

代碼如下:

#includeusing namespace std;

class A
{public:
	virtual void func(int val = 1)
	{cout<< "A ->"<< val<< endl;
	}

	virtual void test()
	{func();
	}
};

class B : public A
{public:
	virtual void func(int val = 0)
	{cout<< "B ->"<< val<< endl;
	}
};

int main()
{B* p = new B;
	p->test();

	return 0;
}

以上代碼的輸出結(jié)果為:
在這里插入圖片描述
分析:

  1. A為父類,B公有繼承A,繼承了A的func和test函數(shù),其中A和B的func函數(shù)構(gòu)成了虛函數(shù)重寫(不要求參數(shù)的缺省值相同),因此構(gòu)成了多態(tài);
  2. main函數(shù)中,B指針p指向B對象,用p調(diào)用了test函數(shù),p的類型是B,而test中this指針的類型是A*,p傳給this,這里用父類指針指向子類對象,構(gòu)成了切片;
  3. 這里this指針是A*類型的,用this調(diào)用func函數(shù),符合父類指針調(diào)用虛函數(shù),符合多態(tài)調(diào)用,多態(tài)調(diào)用時,指針指向那個類對象,就調(diào)用哪個類中的虛函數(shù),顯然p和this指向的都是子類對象,所以這里調(diào)用的是子類中的虛函數(shù);
  4. 虛函數(shù)是接口繼承,普通函數(shù)數(shù)實現(xiàn)繼承;虛函數(shù)繼承時,直接將父類的函數(shù)接口繼承下來,與子類的接口是無關(guān)的,子類重寫的是實現(xiàn),這里的接口是父類的接口,val的缺省值是1,因此函數(shù)最終的輸出結(jié)果為:B ->1,選B。

如果將代碼改成以下形式:

class A
{public:
	virtual void func(int val)//去掉缺省值
	{cout<< "A ->"<< val<< endl;
	}

	virtual void test()
	{func(1);
	}
};

class B : public A
{public:
	void func(int val)
	{cout<< "B ->"<< val<< endl;
	}
};

int main()
{//Test();

	A* p = new B;//用父類的指針指向子類對象
	p->test();

	return 0;
}

子類和父類的func依然構(gòu)成虛函數(shù)重寫;
這里用父類的指針指向子類對象,發(fā)生了切片,但指向的還是子類的對象,所以調(diào)用的函數(shù)還是子類中的虛函數(shù),結(jié)果還是:B ->1;
在這里插入圖片描述
最終結(jié)果與p的指針類型無關(guān),只與它指向的對象有關(guān)。

三、抽象類

在虛函數(shù)的后面寫上 = 0,這個函數(shù)就是純虛函數(shù),包含純虛函數(shù)的類叫做抽象類(接口類),抽象類不能實例化出對象,派生類繼承抽象類后也不能實例化出對象,只有派生類重寫了虛函數(shù),才能實例化對象,純虛函數(shù)規(guī)范了派生類必須重寫,更好的體現(xiàn)出了接口繼承。
代碼如下:

class Car             //把不想實例化出對象的父類定義為抽象類
{public:
	virtual void Drive() = 0;
};

class Benz : public Car
{public:
	virtual void Drive(int)     //如果子類繼承了抽象類卻未完成虛函數(shù)重寫,就會報錯
	{cout<< "Benz - 舒適"<< endl;
	}
};

class BMW : public Car
{public:
	virtual void Drive()
	{cout<< "BMW - 操控"<< endl;
	}
};

int main()
{Car c1;
	Benz c2;
	BMW c3;

	return 0;
}

在這里插入圖片描述
1.抽象類一般用于定義接口,將不想實例化出對象的類定義為抽象類;
2.抽象函數(shù)強制子類完成虛函數(shù)的重寫,不重寫就無法實例化,而override是檢查語法是否完成重寫;

四、多態(tài)的原理 1、虛函數(shù)表

創(chuàng)建如下對象:

class Base
{public:
	virtual void func()
	{cout<< "func"<< endl;
	}
private:
	int _b = 0;
};

int main()
{Base b;
	cout<< sizeof(b)<< endl;

	return 0;
}

我么可以發(fā)現(xiàn)sizeof(b)的結(jié)果是8,再看b對象實例化后的成員
在這里插入圖片描述
可以發(fā)現(xiàn)在成員_b的上面還有一個_vfptr的成員,這叫做虛函數(shù)表指針;帶有虛函數(shù)的類對象,其成員中都有一個虛函數(shù)表指針,因為選虛函數(shù)要放到虛函數(shù)表中,也簡稱虛表。
將Base繼承給子類,代碼如下:

class Base
{public:
	virtual void func1()
	{cout<< "Base::func1"<< endl;
	}
	virtual void func2()             //加一個虛函數(shù)func2
	{cout<< "Base::func2"<< endl;
	}
	void func3()                     //加一個普通函數(shù)func3
	{cout<< "Base::func3"<< endl;
	}

private:
	int _b = 1;
};

class Derive : public Base
{public:
	virtual void func1()                //重寫父類虛函數(shù)
	{cout<< "Derive::func1"<< endl;
	}
private:
	int _d = 2;
};

int main()
{Base b;
	cout<< sizeof(b)<< endl;

	Derive d;

	return 0;
}

通過監(jiān)視窗口我們可以看到:
在這里插入圖片描述
1.子類對象d中也有一個虛函數(shù)表指針,且和父類對象b的虛表指針不同,由于子類對func1完成了重寫,虛表中的func1就是子類重寫后的Detive::func1;
2.func2是虛函數(shù),繼承下來也會放進(jìn)子類的虛表,而func3不是虛函數(shù),不會放進(jìn)虛表;
3.虛表本身是一個放函數(shù)指針的數(shù)組,一般情況最后會放一個nullptr(vs環(huán)境下);
4.虛表存放的是虛函數(shù)的函數(shù)指針,不是虛函數(shù),虛函數(shù)跟普通函數(shù)一樣,都存放在代碼段。

2、多態(tài)的原理

在這里插入圖片描述
在這里插入圖片描述
通過對匯編代碼的分析,我們可以總結(jié)出:
1.滿足多態(tài)以后的函數(shù)調(diào)用,不是在編譯時確定的,是運行起來以后再到對象中找的,程序運行時取對象中的虛表指針找到函數(shù)地址,再去調(diào)用;
2.普通函數(shù)的調(diào)用,是在編譯鏈接時就確定函數(shù)的地址,運行時直接調(diào)用。

五、單繼承和多繼承關(guān)系的虛函數(shù)表 1、單繼承中的虛表

代碼如下:

class Base
{public:
	virtual void func1()
	{cout<< "Base::func1"<< endl;
	}
	virtual void func2()
	{cout<< "Base::func2"<< endl;
	}

private:
	int _b = 1;
};

class Derive : public Base
{public:
	virtual void func1()
	{cout<< "Derive::func1"<< endl;
	}
	virtual void func3()
	{cout<< "Derive::func3"<< endl;
	}
	virtual void func4()
	{cout<< "Derive::func4"<< endl;
	}

private:
	int _d = 2;
};

在這里插入圖片描述
通過監(jiān)視窗口看不見func3和func4,我們可以使用代碼打印虛表中的函數(shù):

class Base
{public:
	virtual void func1()
	{cout<< "Base::func1"<< endl;
	}
	virtual void func2()
	{cout<< "Base::func2"<< endl;
	}

private:
	int _b = 1;
};

class Derive : public Base
{public:
	virtual void func1()
	{cout<< "Derive::func1"<< endl;
	}
	virtual void func3()
	{cout<< "Derive::func3"<< endl;
	}
	virtual void func4()
	{cout<< "Derive::func4"<< endl;
	}

private:
	int _d = 2;
};

typedef void(*VFPTR) ();     //將指向返回值為void、沒有參數(shù)的類型的函數(shù)的指針重定義為VFPTR
void PrintVTable(VFPTR vTable[])
{//依次取虛表中的指針打印并調(diào)用,調(diào)用就可以看出存的是哪個函數(shù)
	cout<< "虛表地址>"<< vTable<< endl;
	for (int i = 0; vTable[i] != nullptr; i++)
	{printf("第%d個虛函數(shù)地址:0x%x", i, vTable[i]);//打印地址
		VFPTR f = vTable[i];//用函數(shù)指針取出虛函數(shù)地址
		f();//調(diào)用
	}
	cout<< endl;
}

int main()
{Base b1;
	Base b2;
	Derive d;

	VFPTR* vTableb1 = (VFPTR*)(*((int*)&b1));//將b對象的地址取出,強轉(zhuǎn)成int*,再解引用,就取出了b的頭四個字節(jié)的數(shù)據(jù),這個就是指向虛表的指針
										   //再強轉(zhuǎn)成VFPTR*,因為虛表就是VFPTR類型的數(shù)組
	PrintVTable(vTableb1);

	VFPTR* vTableb2 = (VFPTR*)(*((int*)&b2));
	PrintVTable(vTableb2);


	VFPTR* vTabled = (VFPTR*)(*((int*)&d));
	PrintVTable(vTabled);

	return 0;
}

在這里插入圖片描述
在這里插入圖片描述
我么可以看出,在vs下:
1.同一個類型的對象,共用一個虛表(b1和b2);
2.不管是否完成重寫名子類虛表和父類虛表都不是同一個;
3.單繼承中,子類的所有虛函數(shù),包括重寫父類的虛函數(shù)和未重寫的虛函數(shù),都放在同一個虛表中。

2、多繼承中的虛表

代碼如下:

class Base1
{public:
	virtual void func1()
	{cout<< "Base1::func1"<< endl;
	}
	virtual void func2()
	{cout<< "Base1::func2"<< endl;
	}

private:
	int _b1 = 1;
};

class Base2
{public:
	virtual void func1()
	{cout<< "Base2::func1"<< endl;
	}
	virtual void func2()
	{cout<< "Base2::func2"<< endl;
	}

private:
	int _b2 = 2;
};


class Derive : public Base1, public Base2
{public:
	virtual void func1()
	{cout<< "Derive::func1"<< endl;
	}
	virtual void func3()
	{cout<< "Derive::func3"<< endl;
	}

private:
	int _d = 3;
};

typedef void(*VFPTR) ();     //將指向返回值為void、沒有參數(shù)的類型的函數(shù)的指針重定義為VFPTR
void PrintVTable(VFPTR vTable[])
{//依次取虛表中的指針打印并調(diào)用,調(diào)用就可以看出存的是哪個函數(shù)
	cout<< "虛表地址>"<< vTable<< endl;
	for (int i = 0; vTable[i] != nullptr; i++)
	{printf("第%d個虛函數(shù)地址:0x%x", i, vTable[i]);//打印地址
		VFPTR f = vTable[i];//用函數(shù)指針取出虛函數(shù)地址
		f();//調(diào)用
	}
	cout<< endl;
}

int main()
{Derive d;

	VFPTR* vTabled1 = (VFPTR*)(*((int*)&d));
	PrintVTable(vTabled1);

	VFPTR* vTabled2 = (VFPTR*)(*(int*)((char*)&d + sizeof(Base1)));//從Base2的虛表中取虛函數(shù)地址
	PrintVTable(vTabled2);


	return 0;
}

Derive多繼承Base1和Base2,其中Derive重寫了func1,而func1既是Base1的虛函數(shù),也是Base2的虛函數(shù),func3是Derive自己的虛函數(shù),運行結(jié)果如下:
在這里插入圖片描述
在這里插入圖片描述

可以看出在多繼承下:
1.子類中每一個繼承的父類都有自己的虛表,存放父類中的虛函數(shù);
2.子類中重寫的虛函數(shù)會覆蓋子類中父類虛表對應(yīng)的虛函數(shù),Base1和Base2中的func1都沒覆蓋為了Derive::func1;
3.子類中繼承的Base1中的func1和Base2中的func1的地址不同,但它們都是Derive重寫后的虛函數(shù),最終調(diào)用的是同一個func1,只是中間多了一個步驟;
4.子類未重寫的的虛函數(shù)放在第一個繼承的父類的虛表中;
在這里插入圖片描述

六、多態(tài)常見面試問題 1.例題

以下程序的輸出結(jié)果是:
在這里插入圖片描述
B和C都是虛繼承A,D多繼承B和C,所以B和C在D中共享一個A,所以B和C都不能去初始化D中的A對象,只能在D中單獨進(jìn)行A的初始化;
初始化是按照類聲明的順序來的,不是按照初始化列表的順序,所以在D中先初始化A對象,在初始化B和C,這事就不會重復(fù)初始化A了,最后初始化D,所以答案選A。

2.inline函數(shù)可以是虛函數(shù)嗎

可以,inline函數(shù)是沒有地址的,而且inline只是對編譯器的一個建議,當(dāng)一個inline函數(shù)是虛函數(shù)時,在多態(tài)調(diào)用以后,inline就失效了,因為虛函數(shù)要放進(jìn)虛表中。

3.靜態(tài)成員函數(shù)可以是虛函數(shù)嗎

不可以,static函數(shù)沒有this指針,可以直接使用類名::函數(shù)名()的方式調(diào)用,而使用類名::函數(shù)名()的方式無法訪問對象的虛表,因此靜態(tài)成員函數(shù)無法放進(jìn)虛表,虛函數(shù)是為了實現(xiàn)多態(tài),多態(tài)運行時都是去虛表中找決議,靜態(tài)成員函數(shù)都是在編譯時就決議了,因此它是虛函數(shù)沒有價值。

4.構(gòu)造函數(shù)可以是虛函數(shù)嗎

不可以,因為虛函數(shù)是為了實現(xiàn)多態(tài)調(diào)用,運行時去虛表中找對應(yīng)的虛函數(shù)進(jìn)行調(diào)用,對象中的虛表指針都是在構(gòu)造函數(shù)初始化列表階段才初始化的,構(gòu)造函數(shù)是虛函數(shù)沒有意義。

5.析構(gòu)函數(shù)可以是虛函數(shù)嗎

可以,并且最好把基類的析構(gòu)函數(shù)定義為虛函數(shù),詳情參考 二-5-3。

6.拷貝構(gòu)造和賦值可以是虛函數(shù)嗎

拷貝構(gòu)造不可以,因為拷貝構(gòu)造也是構(gòu)造函數(shù),參考上面的構(gòu)造函數(shù);
賦值重載operator==()可以,但是沒有實際價值。

7.對象訪問普通函數(shù)快還是虛函數(shù)快

如果虛函數(shù)不構(gòu)成多態(tài),是一樣快的;
如果虛函數(shù)構(gòu)成多態(tài),調(diào)用普通函數(shù)比較快,因為構(gòu)成多態(tài)調(diào)用虛函數(shù)時,運行中需要到虛表中去查找。

8.虛函數(shù)表是在什么階段生成的,存在哪里

虛函數(shù)表是在編譯階段就生成好的,存在代碼段(常量區(qū));
構(gòu)造函數(shù)初始化列表階段初始化的是虛函數(shù)表指針,對象中存的也是虛函數(shù)表指針。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前名稱:C++知識點--多態(tài)-創(chuàng)新互聯(lián)
鏈接地址:http://muchs.cn/article10/ddoego.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站虛擬主機、關(guān)鍵詞優(yōu)化軟件開發(fā)、外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)