重載繼承的初始化
1)如果類A和類B都同時繼承自類X,類C繼承自A和B,那麼在創建類C的時候,類X的構造和析構函數
會被執行兩次,因爲類C在創建的時候,分別會去創建類A和類B,而類A和類B又會去創建類X,所以
就類X會被創建兩次
2)如果類X中有函數Fun,那麼類C在調用的時候需要指定調用哪個父類所繼承的Fun函數,例如:c->A::Fun()
class X
{
public:
X(){}
virtual ~X(){}
virtual void Fun()
{
cout<<"Class X"<<endl;
}
};
class A:public X
{
public:
A(int i):a(i){}
virtual ~A(){}
virtual void print()
{
cout<<"Class A - "<<a<<endl;
}
private:
int a;
};
class B:public X
{
public:
B(int i):a(i){}
virtual ~B(){}
virtual void print()
{
cout<<"Class B - "<<a<<endl;
}
private:
int a;
};
class C:public A, public B
{
public:
//基類A和B的構造函數都是帶參的,所以子類需要對其初始化,順序隨意
C(int i, int j, int k):A(i),B(j),a(k){}
virtual ~C(){}
virtual void print()
{
cout<<"Class C - "<<a<<endl;
}
private:
int a;
};
int main()
{
C *c = new C(1,2,3);
//如果多個基類中擁有相同的函數名,需要用::作用域標識符指出調用哪一個基類的函數,避免二義性
c->A::print();
c->B::print();
c->print();
//如果類A和類B都同時繼承自類X,那麼在創建類C的時候,類X的構造和析構函數會被執行兩次,因爲
//類C在創建的時候,分別會去創建類A和類B,而類A和類B又會去創建類X,所以就類X會被創建銷燬兩次
//如果類X中有函數Fun,那麼類C在調用的時候需要指定調用哪個父類所繼承的Fun函數
c->A::Fun();
//c->B::Fun();
delete c;
return 0;
}
再談虛基類 前往以前的筆記
虛基類可以避免多重繼承時函數調用的二義性,同理,也可以避免最上層的基類(這裏指類X)被創建銷燬兩次
class X
{
public:
X(){cout<<"X構造函數"<<endl;}
virtual ~X(){cout<<"X析構函數"<<endl;}
virtual void Fun()
{
cout<<"Class X"<<endl;
}
};
//說明類X爲虛基類
class A:virtual public X
{
public:
A(int i):a(i){cout<<"A構造函數"<<endl;}
virtual ~A(){cout<<"A析構函數"<<endl;}
private:
int a;
};
class B:virtual public X
{
public:
B(int i):a(i){cout<<"B構造函數"<<endl;}
virtual ~B(){cout<<"B析構函數"<<endl;}
private:
int a;
};
class C:public A, public B
{
public:
//基類A和B的構造函數都是帶參的,所以子類需要對其初始化,順序隨意
//因爲類X被限定只爲子類產生一個實例,所以這裏也可以對類X進行初始化
C(int i, int j, int k):/*X(...),*/A(i),B(j),a(k){cout<<"C構造函數"<<endl;}
virtual ~C(){cout<<"C析構函數"<<endl;}
private:
int a;
};
int main()
{
//類X只會被創建銷燬一次,
C *c = new C(1,2,3);
//虛基類可以避免繼承中的函數二義性
c->Fun();
delete c;
return 0;
}
純虛函數和抽象類
將一個虛函數初始化爲0,這個函數就變成了純虛函數,例如:
virtual int fun() = 0;
這種函數沒有任何具體功能,不能直接調用它,有純虛函數的類是抽象的,所以也不能實例化
一個類如果繼承了抽象類,那麼這個類就必須實現該抽象類中的方法
如果這個子類沒有全部覆蓋抽象基類的方法,那麼這個子類也會變成一個抽象類
class X
{
public:
virtual void print() = 0;
};
class A:public X
{
public:
A(){}
~A(){}
//類A必須實現抽象類裏面的純虛函數
void print(){cout<<"Class A"<<endl;}
//或者繼續把這個函數設爲虛函數,那此時類A也屬於抽象類
//void print() = 0;
};
int main()
{
A *pA = new A();
pA->print();
return 0;
}