1. 程式人生 > >類的繼承與派生(虛擬繼承Virtual)

類的繼承與派生(虛擬繼承Virtual)

類的繼承與派生,由於派生類會完全繼承基類的公有成員。如果從多個基類繼承,那麼就會存在同一個基類的成員會被繼承多個,造成成員變數的冗餘。未解決這個問題,C++提供了虛擬繼承的機制,已達到消除成員變數的冗餘。

#include <iostream>

using namespace std;
class Vehicle{
public:
	int MaxSpped;
	int Weight;
	void Run(){ cout << "Vehicle run." << endl; }
	void Stop(){ cout << "Vehicle stop." << endl; }
};

class Bicycle :virtual public Vehicle{
public:
	int Height;
};

class Motorcar :virtual public Vehicle{
public:
	int SeatNum;
};

class Motorcycle :public Bicycle, public Motorcar{

};
int main()
{
	Motorcycle m;
	m.Height = 1;
	m.SeatNum = 2;
	m.Weight = 100;
	m.MaxSpped = 60;
	m.Run();
	m.Stop();

	return 0;
}
單步除錯觀察的m的成員變數如下圖所示:


例項應用:

定義一個基類Account,資料成員包含string類變數userName用於儲存賬戶主人姓名,函式成員包括預設建構函式、帶參建構函式用於初始化資料成員和輸出姓名的成員函PrintName()。從Account類派生出CreditAccount類,增加整型資料成員credit用於記錄該使用者信用額度,函式成員包括帶參建構函式用於初始化資料成員和輸出賬戶資訊的成員函式PrintInfo()。要求:在函式PrintInfo()中需要呼叫基類的成員函式PrintName()

#include <iostream>
#include <string>
using namespace std;

class Account
{
	string userName;
public:
	Account(){};
	Account(string _name);
	void  PrintUserName();
};

class CreditAccount : public Account
{
public:
	CreditAccount(string _name, int _credit);
	void PrintInfo();
private:
	int credit;
};

//請實現Account建構函式Account(char *name)
Account::Account(string _name)
{
	userName = _name;
}
//請實現Account的PrintUserName()函式
void Account::PrintUserName()
{
	cout << userName << endl;
}
//請實現CreditAccount類的建構函式CreditAccount(char* name, long number)
CreditAccount::CreditAccount(string _name, int _credit) :Account(_name), credit(_credit)
{
	
}
//請實現CreditAccount類的PrintInfo()函式
void CreditAccount::PrintInfo()
{
	Account::PrintUserName();
	//PrintUserName();
	cout << credit << endl;
}

int main()
{
	CreditAccount a("I Love CPP", 10000);
	a.PrintInfo();
	return 0;
}
執行結果:

多繼承的問題

多繼承時,派生類在宣告的基類順序,決定了日後各個基類構造和析構的順序。

下面的程式碼聲明瞭三個基類Base1Base2Base3,然後從這三個基類按照公有方式派生出類Derived。在每個類中分別定義帶一個整型引數的建構函式和解構函式輸出提示資訊,建構函式的提示資訊中需要包含整型引數的數值。請將下面的程式碼補充完整,使得輸出結果與樣例輸出相同,注意:測試資料有多組。

#include <iostream>
using namespace std;

class Base1
{
public:
	Base1(int x);
	~Base1();
};

class Base2
{
public:
	Base2(int x);
	~Base2();
};
class Base3
{
public:
	Base3(int x);
	~Base3();
};

class Derived :public Base2,public Base1,public Base3  //此處宣告基類的順序決定了構造和析構基類的順序
{
public:
	Derived(int x1, int x2, int x3, int x4);
	~Derived();

};

Base1::Base1(int x)
{
	cout << "Base1 constructor called " << x << endl;
}

Base1::~Base1()
{
	cout << "Base1 destructor called" << endl;
}
//依照Base1類中的程式碼實現其它類的建構函式和解構函式 
Base2::Base2(int x)
{
	cout << "Base2 constructor called " << x << endl;
}

Base2::~Base2()
{
	cout << "Base2 destructor called" << endl;
}
Base3::Base3(int x)
{
	cout << "Base3 constructor called " << x << endl;
}

Base3::~Base3()
{
	cout << "Base3 destructor called" << endl;
}

Derived::Derived(int x1, int x2, int x3, int x4) :Base1(x2), Base2(x3),Base3(x4)
{
	cout << "Derived constructor called " <<x1 <<endl;
}
Derived::~Derived()
{
	cout << "Derived destructor called" << endl;
}
int main()
{
	int x[4];
	for (int i = 0; i < 4; ++i)
		cin >> x[i];
	Derived d(x[0], x[1], x[2], x[3]);
	return 0;
}

執行結果:


來自清華大學MOOC課件