一、菱形繼承
代碼演示:
創建: 1.Farmer類,數據成員:m_strName,成員函數:構造、析構、sow()
2.Worker類,數據成員:m_strCode,成員函數:構造、析構、carry()
3.MigrantWorker類,數據成員:無,成員函數:構造、析構
4.Person類,數據成員:m_strColor,成員函數:構造、析構、printColor()
派生關係:Person ->Farmer->MigrantWorker;Person ->Worker->MigrantWorker;Worker和Farmer->MigrantWorker
Person.h
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(string color = "blue");
virtual ~Person();
void printColor();
protected:
string m_strColor;
};
Person.cpp
#include"Person.h"
Person::Person(string color)
{
m_strColor = color;
cout<<"Person()"<<endl;
}
Person::~Person()
{
cout<<"~Person()"<<endl;
}
void Person::printColor()
{
cout<<m_strColor<<endl;
cout<<"Person--printColor()"<<endl;
}
Farmer.h
#include"Person.h"
class Farmer:public Person
{
public:
Farmer(string name = "Jack",string color = "blue");
virtual ~Farmer();
void sow();
protected:
string m_strName;
};
Farmer.cpp
#include"Farmer.h"
Farmer::Farmer(string name,string color):Person("Farmer"+color)
{
m_strName = name;
cout<<"Farmer()"<<endl;
}
Farmer::~Farmer()
{
cout<<"~Farmer()"<<endl;
}
void Farmer::sow()
{
cout<<m_strName<<endl;
cout<<"Farmer--sow()"<<endl;
}
Worker.h
#include"Person.h"
class Worker:public Person
{
public:
Worker(string code = "001",string color = "blue");
virtual ~Worker();
void carry();
protected:
string m_strCode;
};
Worker.cpp
#include"Worker.h"
//爲了證明在MigrantWorker類中已經存在了兩份person的數據,將字符串worker也傳遞給Person,字符串之間可以拼接
Worker::Worker(string code,string color):Person("Worker"+color)//使用初始化列表將值向下進行傳遞,好處是如果Person當中有其他的邏輯,我們就不需要重複去寫,而可以將值直接地傳遞給person的構造函數
{
m_strCode = code;
cout<<"Worker()"<<endl;
}
Worker::~Worker()
{
cout<<"~Worker()"<<endl;
}
void Worker::carry()
{
cout<<m_strCode<<endl;
cout<<"Worker--carry()"<<endl;
}
MigrantWorker.h
#include"Worker.h"
#include"Farmer.h"
class MigrantWorker:public Farmer,public Worker
{
public:
MigrantWorker(string name,string code,string color);
~MigrantWorker();
};
MigrantWorker.cpp
#include"MigrantWorker.h"
MigrantWorker::MigrantWorker(string name,string code,string color):Farmer(name,color),Worker(code,color)
{
cout<<"MigrantWorker()"<<endl;
}
MigrantWorker::~MigrantWorker()
{
cout<<"~MigrantWorker()"<<endl;
}
main.cpp
#include"MigrantWorker.h"
int main(void)
{
MigrantWorker *p = new MigrantWorker("Merry","100","yellow");
p->Farmer::printColor();//在MigrantWorker類中已經存在了兩份person的數據->解決用虛繼承
p->Worker::printColor();
delete p;
p = NULL;
return 0;
}
運行結果:
因爲MigrantWorker分別繼承了Worker和Farmer,worker和farmer的頭文件中都有person.h,所以MigrantWorker包含了兩份person.h,造成重定義(即在當前工程中,person被聲明瞭兩遍)-->解決用宏定義-->在person.h中加上宏定義即可
在person.h中加上宏定義之後運行:
根據運行結果,發現在MigrantWorker類中已經存在了兩份person的數據-->解決用虛繼承
其餘代碼不變,將worker.h和farmer.h中繼承方式前加上virtual關鍵字
Worker.h
#include"Person.h"
class Worker:virtual public Person//虛繼承
{
public:
Worker(string code = "001",string color = "blue");
virtual ~Worker();
void carry();
protected:
string m_strCode;
};
Farmer.h
#include"Person.h"
class Farmer:virtual public Person
{
public:
Farmer(string name = "Jack",string color = "blue");
virtual ~Farmer();
void sow();
protected:
string m_strName;
};
運行結果:
使用了virtual關鍵字之後,就形成虛繼承,好處:MigrantWorker所實例化的對象當中只有一份person的數據
運行結果爲blue,說明在虛繼承的情況下作爲菱形繼承最頂層的父類並沒有進行參數的傳遞,參數只使用了頂層父類的默認參數,而無法從子類當中獲得傳入的參數。