------------------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"); 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】