C++ 虚基类
- 概述
- 多重继承的问题
- 虚基类
- 初始化
- 例子
- 总结
概述
虚基类 (virtual base class) 是用关键字 virtual 声明继承的父类.
多重继承的问题
N 类:
class N {
public:int a;void display(){cout << "A::a=" << a <<endl;}
};
A 类:
class A : public N {
public:int a1;
};
B 类:
class B : public N {
public:int a2;
};
C 类:
class C: public A, public B{
public:int a3;void display() {cout << "a3=" << a3 << endl;};
};
main:
int main() {C c1;// 合法访问c1.A::a = 3;c1.A::display();return 0;
}
输出结果:
A::a=3
存在的问题:
- A::a 和 B::a 是 N 类成员的拷贝
- A::a 和 B::a 占用不同的空间
虚基类
我们希望继承间接共同基类时只保留一份成员, 所以虚基类就诞生了. 当基类通过多条派生路径被一个派生类继承时, 该派生类只继承该基类一次.
语法:
class 派生类名: virtual 继承方式 基类名
初始化
通过构造函数的初始化表对虚拟类进行初始化. 例如:
N 类:
class N {
public:int n;N(int n) : n(n) {};
};
A 类:
class A : virtual public N {
public:A(int n) : N(n) {};
};
B 类:
class B : virtual public N {
public:B(int n) : N(n) {};
};
C 类:
class C: public A, public B{
public:C(int n) : N(n), A(n), B(n){};
};
例子
Person 类:
#ifndef PROJECT5_PERSON_H
#define PROJECT5_PERSON_H#include <iostream>
#include <string>
using namespace std;class Person {
protected:string name;char gender;
public:Person(string n, char g) : name(n), gender(g) {}void display() {cout << "name: " << name << endl;cout << "gender: " << gender << endl;}
};#endif //PROJECT5_PERSON_H
Student 类:
#ifndef PROJECT5_STUDENT_H
#define PROJECT5_STUDENT_H#include <string>
#include "Person.h"
using namespace std;class Student : virtual public Person {
protected:double score;
public:Student(string n, char g, double s) : Person(n, g), score(s) {};
};#endif //PROJECT5_STUDENT_H
Teacher 类:
#ifndef PROJECT5_TEACHER_H
#define PROJECT5_TEACHER_H#include <string>
#include "Person.h"
using namespace std;class Teacher : virtual public Person {
protected:string title;
public:Teacher(string n, char g, string t) : Person(n, g), title(t) {};
};#endif //PROJECT5_TEACHER_H
Graduate 类:
#ifndef PROJECT5_GRADUATE_H
#define PROJECT5_GRADUATE_H#include "Teacher.h"
#include "Student.h"
#include <string>
using namespace std;class Graduate : public Teacher, public Student{
private:double wage;
public:Graduate(string n, char g, double s, string t, double w) : Person(n, g), Student(n, g, s), Teacher(n, g, t), wage(w) {};void display() {Person::display();cout << "score: " << score << endl;cout << "title: " << title << endl;cout << "wages: " << wage << endl;};
};#endif //PROJECT5_GRADUATE_H
main:
#include <iostream>
#include "Graduate.h"
using namespace std;int main() {Graduate grad1("小白",'f',89.5,"教授",1234.5);grad1.display();return 0;
}
输出结果:
name: 小白
gender: f
score: 89.5
title: 教授
wages: 1234.5
总结
- 使用多重继承时要十分小心, 否则会进场出现二义性问题
- 不提倡在程序中使用多重继承
- 只有在比较简单和不易出现二义性的情况或实在必要时才使用多重继承
- 能用单一继承解决的问题就不要使用多重继承