多重繼承容易引起的問題就是因為繼承的成員同名而產生的二義性問題。
例:類A和類B中都有成員函數display和數據成員a,類C是類A和類B的直接派生類
情況一:
class A
{public:int a;void display();
};
class B
{public:int a;void display;
};
class C:public A,public B//公用繼承
{public:int b;void show();
};
如果在main函數中定義類C的對象c1并調用數據成員a和成員函數display
C c1;
c1.a=3;//引用c1的數據成員a
c1.dispaly();//調用c1的成員函數display
由于基類A和基類B都有數據成員a和成員函數display,編譯系統無法判別要訪問的是哪一個基類的成員,因此,程序編譯出錯。
解決方法1、用基類名來限定
c1.A::a=3;//引用c1對象中的基類A的數據成員a
c2.A::display();//引用c1的成員函數display
若派生類C中的成員函數show訪問基類A的display和a,可以不必寫對象名而直接寫
c1.A::A=3;//引用c1對象中的基類A的數據成員a
c1.A::display();//調用c1對象中的基類A的成員函數display
不同的成員函數,只有在函數名和參數個數相同、類型相匹配的情況下才發生同名覆蓋,如果只有函數名相同而參數不同,不會發生同名覆蓋,而屬于函數重載。
虛基類的作用:
C++提供虛基類的方法,使得在繼承間接共同基類時只保留一份成員。
使用虛基類發方法:
class A//聲明基類A
{.........};
class B:virtual public A//聲明類B是類A的公用派生類,A是B的虛基類
{......};
class C:virtual public A//聲明類C是類A的公用派生類,A是C的虛基類
{......};
注意:虛基類并不是在聲明基類時聲明的,而是在聲明派生類時,指定繼承方式時聲明的。
聲明虛基類的一般形式為:
class 派生類名:virtual 繼承方式 基類名
經過上面的聲明后,當基類通過多條派生路徑被一個派生類繼承時,該派生類只繼承該基類一次,也就是說,基類成員只保留一次。
二、虛基類的初始化
class A//定義基類A
{
? ? ? ? A(int i){}//基類構造函數,有一個參數
.......};
class B:virtual public A//A作為B的虛基類
{
? ? ? ? B(int n):A(n){}//類B構造函數,在初始化表中對虛基類初始化
...};
class C:virtual public A//A作為C的虛基類
{
? ? ? ? C(int n):A(n){}
......};//類C的構造函數,在初始化表中對虛基類初始化
class D:public B,public C//類D的構造函數,在初始化表中對所有基類初始化
{
? ? ? ? D(int n):A(n),B(n),C(n){}
......};
應用:
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:Person(string nam, char s, int a) {name = nam;sex = s;age = a;}
protected:string name;char sex;int age;
};
class Teacher :virtual public Person
{
public:Teacher(string nam, char s, int a, string t) :Person(nam, s, a){title = t;}
protected:string title;
};
class Student :virtual public Person
{
public:Student(string nam, char s, int a, float sco) :Person(nam, s, a){score = sco;}
protected:float score;
};
class Graduate :virtual public Teacher, public Student//Teacher和Student為直接基類
{
public:Graduate(string nam, char s, int a, string t, float sco, float w) :Person(nam, s, a), Teacher(nam, s, a, t), Student(nam, s, a, sco){wage = w;}void show(){cout << "name:" << name << endl;cout << "age:" << age << endl;cout << "sex:" << sex << endl;cout << "title:" << title << endl;cout << "score:" << score << endl;cout << "wage:<" << wage << endl;}
private:float wage;
};
int main()
{Graduate grad1("yan_tong", 'f', 24, "saadistant", 99.9, 3000);grad1.show();return 0;
}
運行結果: