概述
當在多條繼承路徑上有一個公共的基類,在這些路徑中的某幾條匯合處,這個公共的基類就會產生多個實例(或多個副本),若只想保存這個基類的一個實例,可以將這個公共基類說明爲虛基類.
classx1:virtual public x
{
};
classx2:virtual public x
{
};
虛基類的初始化
虛基類的初始化與一般多繼承的初始化在語法上是一樣的,但構造函數的調用次序不同.
派生類構造函數的調用次序有三個原則:
(1)虛基類的構造函數在非虛基類之前調用;
(2)若同一層次中包含多個虛基類,這些虛基類的構造函數按它們說明的次序調用;
(3)若虛基類由非虛基類派生而來,則仍先調用基類構造函數,再調用派生類的構造函數.
C++的虛基類
在派生類繼承基類時,加上一個virtual關鍵詞則爲虛擬基類繼承,如:
classderive:virtual public base
{
};
虛基類主要解決在多重繼承時,基類可能被多次繼承,虛基類主要提供一個基類給派生類,如:
classB
{
};
classD1:public B
{
};
classD2:public B
{
};
classC:public D1,public D2
{
};
這裏C在D1,D2上繼承,但有兩個基類,造成混亂。因而使用虛基類,即:
classB
{
};
classD1:virtual public B
{
};
classD2:virtualpublicB
{
};
classC:public D1,public D2
在使用虛基類時要注意
(1) 一個類可以在一個類族中既被用作虛基類,也被用作非虛基類。
(2) 在派生類的對象中,同名的虛基類只產生一個虛基類子對象,而某個非虛基類產生各自的子對象。
(3) 虛基類子對象是由最派生類的構造函數通過調用虛基類的構造函數進行初始化的。
(4) 最派生類是指在繼承結構中建立對象時所指定的類。
(5) 派生類的構造函數的成員初始化列表中必須列出對虛基類構造函數的調用;如果未列出,則表示使用該虛基類的缺省構造函數。
(6) 從虛基類直接或間接派生的派生類中的構造函數的成員初始化列表中都要列出對虛基類構造函數的調用。但只有用於建立對象的最派生類的構造函數調用虛基類的構造函數,而該派生類的所有基類中列出的對虛基類的構造函數的調用在執行中被忽略,從而保證對虛基類子對象只初始化一次。
(7) 在一個成員初始化列表中同時出現對虛基類和非虛基類構造函數的調用時,虛基類的構造函數先於非虛基類的構造函數執行。
虛基類在繼承中的優先性
遵循兩個原則,而且按順序優先滿足:1 先調用完所以基類,再調用子類;2 先調用虛擬基類,再調用非虛擬基類。
#ifndef BASE1_H
#define BASE1_H
#include <iostream>
using std::cout;
using std::endl;
class base1
{
public:
base1()
{
cout << "base1" << endl;
}
};
#endif
#ifndef BASE2_H
#define BASE2_H
#include <iostream>
using std::cout;
using std::endl;
class base2
{
public:
base2()
{
cout << "base2" << endl;
}
};
#endif
#ifndef SUB1_H
#define SUB1_H
#include <iostream>
using std::cout;
using std::endl;
#include "base1.h"
#include "base2.h"
class sub1 : public base1,public base2
{
public:
sub1()
{
cout << "sub1" << endl;
}
};
#endif
#ifndef SUB2_H
#define SUB2_H
#include <iostream>
using std::cout;
using std::endl;
#include "base1.h"
#include "base2.h"
class sub2 : public base2,public base1
{
public:
sub2()
{
cout << "sub2" << endl;
}
};
#endif
#ifndef TEST_H
#define TEST_H
#include <iostream>
using std::cout;
using std::endl;
#include "sub1.h"
#include "sub2.h"
class test1 : public sub1,virtual public sub2
{
public:
test1()
{
cout << "test1" << endl;
}
};
class test2 : public sub2,public sub1
{
public:
test2()
{
cout << "test1" << endl;
}
};
#endif
#include <iostream>
using std::cin;
#include "test.h"
int main()
{
int i;
test1 a;
cin >> i ;
}
base2 base1 sub2 base1 base2 sub1 test1