C++多重繼承、純虛函數和抽象類

重載繼承的初始化

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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章