虚继承

------------------siwuxie095

   

   

   

   

   

   

   

   

   

   

   

   

看如下实例:

   

4 个类,其中:类 A 是父类,类 B 和 类 C 都继承 类 A,

D 继承了 类 B 和 类 C,称这种继承关系为 菱形继承

   

   

   

   

在菱形继承中,既有多继承,又有多重继承:

   

   

   

   

   

   

那么问题来了:

   

当实例化 D 的对象时,发现:D 是从 B 继承来的,B 是从 A 继承来的,

D 也是从 C 继承来的,C 是从 A 继承来的

   

这样,D 中将含有两个完全一样的 A 的数据,这种情况是不能容忍的,

因为在一个对象中有两份完全相同的数据,无法承担这种冗余数据带来

的系统开销,所以必须要解决

   

   

   

   

也许,你会说在实际的工作中会遇到这么复杂的情况吗?

看如下实例:人、工人、农民、农民工间的菱形继承关系

   

   

   

   

那么,可以使用 虚继承 来解决这种典型的菱形继承关系带来的数据冗余问题

   

   

   

   

虚继承

   

   

虚继承 是继承的一种方式,关键字:virtual

   

   

看如下实例:virtual 可以写在 public 的前面 或 后面,推荐前面

   

其中:Worker 和 Farmer 都 虚继承 自 Person

   

   

   

   

在使用时:

   

MigrantWorker 可以继承自 Worker 和 Farmer 这两个类,并称 Worker

Farmer 为 虚基类,当使用 MigrantWorker 实例化一个对象时,它当

中只含有一份 Person 的数据

   

   

   

   

   

   

   

   

程序 1:不使用虚继承

   

Person.h:

   

#ifndef PERSON_H

#define PERSON_H

   

//重定义,即在当前的工程中,Person被定义了两遍,因为在子类包含了两个 Person.h

//

//在菱形继承中重定义必然会出现

//用宏定义来解决重定义,避免了重复包含

//具体用法:在公共被继承的类中写上宏定义

//

//推荐不是公共被继承的类也写上,将来这个类被其他类继承时就不会出现重定义

   

#include <string>

using namespace std;

   

   

class Person

{

public:

Person(string color = "yellow");

virtual ~Person();//虚析构函数

void printColor();

protected:

string m_strColor;//肤色

};

   

   

#endif

   

   

   

Person.cpp:

   

#include "Person.h"

#include <iostream>

using namespace std;

   

   

Person::Person(string color)

{

m_strColor = color;

cout << "Person()" << endl;

}

   

Person::~Person()

{

cout << "~Person()" << endl;

}

   

void Person::printColor()

{

cout << "Person--printColor()" << endl;

cout << m_strColor << endl;

}

   

   

   

Farmer.h:

   

#include "Person.h"

#include <string>

using namespace std;

   

   

class Farmer :public Person

{

public:

Farmer(string name = "Jack", string color = "yellow");

virtual ~Farmer();//虚析构函数

void sow();

protected:

string m_strName;

};

   

   

   

Farmer.cpp:

   

#include "Farmer.h"

#include <iostream>

using namespace std;

   

   

//colorstring型数据所以可以用 + 的形式来将 "Farmer " 同时传进去作为标记

Farmer::Farmer(string name, string color) :Person("Farmer "+color)

{

m_strName = name;

cout << "Farmer()" << endl;

}

   

Farmer::~Farmer()

{

cout << "~Farmer()" << endl;

}

   

void Farmer::sow()

{

cout << "Farmer--sow()" << endl;

cout << m_strName << "," << m_strColor << endl;

}

   

   

   

Worker.h:

   

#include "Person.h"

#include <string>

using namespace std;

   

   

class Worker:public Person

{

public:

//希望Worker可以传入肤色给Person

//使得Person能从Worker的参数列表中拿到肤色的这个参数

Worker(string code = "001", string color = "yellow");

virtual ~Worker();//虚析构函数

void carry();

protected:

string m_strCode;

};

   

   

   

Worker.cpp:

   

#include "Worker.h"

#include <iostream>

using namespace std;

   

   

//colorstring型数据所以可以用 + 的形式来将 "Worker " 同时传进去作为标记

Worker::Worker(string code, string color) :Person("Worker "+color)

{

m_strCode = code;

cout << "Worker()" << endl;

}

   

Worker::~Worker()

{

cout << "~Worker()" << endl;

}

   

void Worker::carry()

{

cout << "Worker--worker()" << endl;

cout << m_strCode << "," << m_strColor << endl;

}

   

   

   

MigrantWorker.h:

   

#include "Farmer.h"

#include "Worker.h"

   

class MigrantWorker:public Farmer,public Worker

{

public:

MigrantWorker(string name, string code, string color);

virtual ~MigrantWorker();//虚析构函数

};

   

   

   

MigrantWorker.cpp:

   

#include "MigrantWorker.h"

#include <iostream>

using namespace std;

   

   

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 <stdlib.h>

#include "MigrantWorker.h"

#include <iostream>

using namespace std;

   

   

int main(void)

{

//从堆中实例化,用指针指向堆中的这块内存

MigrantWorker *p = new MigrantWorker("Merry", "200", "white");

cout << endl;

   

//这两行代码说明了Person类在MigrantWorker类中有两份数据

//MigrantWorker类中有两份继承自Person类的数据数据冗余系统开销太大

p->Farmer::printColor();

p->Worker::printColor();

cout << endl;

   

delete p;

p = NULL;

system("pause");

return 0;

}

   

   

运行一览:

   

   

   

   

   

   

程序 2:使用虚继承

   

Person.h:

   

#ifndef PERSON_H

#define PERSON_H

#include <string>

using namespace std;

   

   

class Person

{

public:

Person(string color = "yellow");

virtual ~Person();

void printColor();

protected:

string m_strColor;

};

   

#endif

   

   

   

Person.cpp:

   

#include "Person.h"

#include <iostream>

using namespace std;

   

   

Person::Person(string color)

{

m_strColor = color;

cout << "Person()" << endl;

}

   

Person::~Person()

{

cout << "~Person()" << endl;

}

   

void Person::printColor()

{

cout << "Person--printColor()" << endl;

cout << m_strColor << endl;

}

   

   

   

Farmer.h:

   

#include "Person.h"

#include <string>

using namespace std;

   

   

class Farmer :virtual public Person //Farmer变成了虚基类

{

public:

Farmer(string name = "Jack", string color = "yellow");

virtual ~Farmer();

void sow();

protected:

string m_strName;

};

   

   

   

Farmer.cpp:

   

#include "Farmer.h"

#include <iostream>

using namespace std;

   

   

Farmer::Farmer(string name, string color) :Person("Farmer "+color)

{

m_strName = name;

cout << "Farmer()" << endl;

}

   

Farmer::~Farmer()

{

cout << "~Farmer()" << endl;

}

   

void Farmer::sow()

{

cout << "Farmer--sow()" << endl;

cout << m_strName << "," << m_strColor << endl;

}

   

   

   

Worker.h:

   

#include "Person.h"

#include <string>

using namespace std;

   

   

class Worker :virtual public Person //Worker变成了虚基类

{

public:

Worker(string code = "001", string color = "yellow");

virtual ~Worker();

void carry();

protected:

string m_strCode;

};

   

   

   

Worker.cpp:

   

#include "Worker.h"

#include <iostream>

using namespace std;

   

   

Worker::Worker(string code, string color) :Person("Worker "+color)

{

m_strCode = code;

cout << "Worker()" << endl;

}

   

Worker::~Worker()

{

cout << "~Worker()" << endl;

}

   

void Worker::carry()

{

cout << "Worker()" << endl;

cout << m_strCode << "," << m_strColor << endl;

}

   

   

   

MigrantWorker.h:

   

#include "Farmer.h"

#include "Worker.h"

   

class MigrantWorker :public Farmer, public Worker

{

public:

MigrantWorker(string name, string code, string color);

~MigrantWorker();

};

   

   

   

MigrantWorker.cpp:

   

#include "MigrantWorker.h"

#include <iostream>

using namespace std;

   

   

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 <stdlib.h>

#include "MigrantWorker.h"

#include <iostream>

using namespace std;

   

int main(void)

{

MigrantWorker *p = new MigrantWorker("Merry", "200", "white");

cout << endl;

   

//此时只会打印出yellow 说明在虚继承的情况下作为菱形继承最顶层的父类,

//并没有进行参数的传递

//

//参数只使用了顶层父类的默认参数而无法从子类中获得传入的参数

p->Farmer::printColor();

p->Worker::printColor();

cout << endl;

   

/*p->carry();

p->sow();*/

delete p;

p = NULL;

system("pause");

return 0;

}

   

   

运行一览:

   

   

   

   

   

   

   

   

【made by siwuxie095】

原文地址:https://www.cnblogs.com/siwuxie095/p/6804282.html