關於C++中虛擬繼續的一些總結剖析。本站提示廣大學習愛好者:(關於C++中虛擬繼續的一些總結剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是關於C++中虛擬繼續的一些總結剖析正文
1.為何要引入虛擬繼續
虛擬繼續是多重繼續中獨有的概念。虛擬基類是為處理多重繼續而湧現的。如:類D繼續自類B1、B2,而類B1、B2都繼續自類A,是以在類D中兩次湧現類A中的變量和函數。為了節儉內存空間,可以將B1、B2對A的繼續界說為虛擬繼續,而A就成了虛擬基類。完成的代碼以下:
class A
class B1:public virtual A;
class B2:public virtual A;
class D:public B1,public B2;
虛擬繼續在普通的運用中很罕用到,所以也常常被疏忽,這也重要是由於在C++中,多重繼續是不推舉的,也其實不經常使用,而一旦分開了多重繼續,虛擬繼續就完整掉去了存在的需要由於如許只會下降效力和占用更多的空間。
2.引入虛繼續和直接繼續會有甚麼差別呢
因為有了直接性和同享性兩個特點,所以決議了虛繼續系統下的對象在拜訪時必定會在時光和空間上與普通情形有較年夜分歧。
2.1時光:在經由過程繼續類對象拜訪虛基類對象中的成員(包含數據成員和函數成員)時,都必需經由過程某種直接援用來完成,如許會增長援用尋址時光(就和虛函數一樣),其實就是調劑this指針以指向虛基類對象,只不外這個調劑是運轉時光接完成的。
2.2空間:因為同享所以不用要在對象內存中保留多份虛基類子對象的拷貝,如許較之多繼續節儉空間。虛擬繼續與通俗繼續分歧的是,虛擬繼續可以避免湧現diamond繼續時,一個派生類中同時湧現了兩個基類的子對象。也就是說,為了包管這一點,在虛擬繼續情形下,基類子對象的結構是分歧於通俗繼續的。是以,它須要多出一個指向基類子對象的指針。
3.口試,面試中常考的C++虛擬繼續的常識點
第一種情形: 第二種情形: 第三種情形 第四種情形:
class a class a class a class a
{ { { {
virtual void func(); virtual void func(); virtual void func(); virtual void func();
}; }; char x; char x;
class b:public virtual a class b :public a }; };
{ { class b:public virtual a class b:public a
virtual void foo(); virtual void foo(); { {
}; }; virtual void foo(); virtual void foo();
假如對這四種情形分離求sizeof(a), sizeof(b)。成果是甚麼樣的呢?上面是輸入成果:(在vc6.0中運轉)
第一種:4,12
第二種:4,4
第三種:8,16
第四種:8,8
想一想這是為何呢?
由於每一個存在虛函數的類都要有一個4字節的指針指向本身的虛函數表,所以每種情形的類a所占的字節數應當是沒有甚麼成績的,那末類b的字節數怎樣算呢?看“第一種”和“第三種”情形采取的是虛繼續,那末這時候候就要有如許的一個指針vptr_b_a,這個指針叫虛類指針,也是四個字節;還要包含類a的字節數,所以類b的字節數就求出來了。而“第二種”和“第四種”情形則不包含vptr_b_a這個指針,這回應當木有成績了吧。
4.c++重載、籠罩、隱蔽的差別和履行方法
既然說到了繼續的成績,那末無妨評論辯論一下常常提到的重載,籠罩和隱蔽
4.1成員函數被重載的特點
(1)雷同的規模(在統一個類中);
(2)函數名字雷同;
(3)參數分歧;
(4)virtual 症結字無關緊要。
4.2“籠罩”是指派生類函數籠罩基類函數,特點是:
(1)分歧的規模(分離位於派生類與基類);
(2)函數名字雷同;
(3)參數雷同;
(4)基類函數必需有virtual 症結字。
4.3“隱蔽”是指派生類的函數屏障了與其同名的基類函數,特點是:
(1)假如派生類的函數與基類的函數同名,然則參數分歧,此時,豈論有沒有virtual症結字,基類的函數將被隱蔽(留意別與重載混雜)。
(2)假如派生類的函數與基類的函數同名,然則參數雷同,然則基類函數沒有virtual 症結字。此時,基類的函數被隱蔽(留意別與籠罩混雜)。
小結:說白了就是假如派生類和基類的函數名和參數都雷同,屬於籠罩,這是可以懂得的吧,完整一樣固然要籠罩了;假如只是函數名雷同,參數其實不雷同,則屬於隱蔽。
4.4 三種情形怎樣履行:
4.4.1 重載:看參數。
4.4.2 隱蔽:用甚麼就挪用甚麼。
4.4.3 籠罩:挪用派生類。