------------------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;
//color是string型数据所以可以用 + 的形式来将 "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;
//color是string型数据所以可以用 + 的形式来将 "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");
return0;
}
运行一览:
程序 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");
return0;
}
运行一览:
【made by siwuxie095】