【C++】虚继承(virtual base classes)
文章目录
- 【C++】虚继承(virtual base classes)
- 1. 使用原因
- 2. 解决方法
- 3. 例题练习
1. 使用原因
在多重继承(Multiple Inheritance) 的情况下,尤其是菱形继承时,容易出现问题,关于菱形继承见下图:
B, C 继承自 A,接着 D 又继承了 B 和 C,相当于 D 继承了两次 A。
已知 B C 继承自 A 类,在 A 类中有变量 a
class A
{
public:
int a;
};
在 B 中定义获取 a 的方法 Get, C 中定义设置 a 的方法 Set,
class B : public A
{
public:
int Get() { return a; }
};
class C : public A
{
public:
void Set(int val) { a = val; }
};
此时 D 类 public 继承 B 和 C
class D : public B, public C
{};
那么使用 D 实例化的对象 dobject,调用 Get 和 Set 接口,所操作的变量 a 为同一个吗?
#include <iostream>
int main(int argc, char* argv[])
{
D dobject;
d.Set(10);
std::cout << d.Get() << std::endl;// undefined value
return 0;
}
答案是否定的,B,C 继承 A,则 B,C 中均有一个 a 变量, B 中的 Get 只能操作 B 中的 a, C 中的 Set 只能操作 C 中的 a ,D 同时拥有了B 和 C 的所有属性,这就是问题所在了。
2. 解决方法
在 B C 继承 A 时,使用虚继承,或者叫虚基类 (virtual base classes) ,继承时额外使用 virtual 关键字
虚继承的语法为
class Derived : public virtual Base { }; // 或 class Derived : virtual public Base { };
也就是:
class B : public virtual A
{
public:
int Get() { return a; }
};
class C : virtual public A
{
public:
void Set(int val) { a = val };
};
此时 D 再正常继承 B,C 则不会出现问题,
虚继承表示构建时,在构建 D 类对象时,构建 B 和 C 时,不构建 B 和 C 类对象中的 A,只构建一次 A ,则在 D 的对象中只存在一个 a 变量
class D : public B, public C
{};
#include <iostream>
int main(int argc, char* argv[])
{
D dobject;
d.Set(10);
std::cout << d.Get() << std::endl;// 10
return 0;
}
3. 例题练习
#include <iostream>
class A {
public:
A(const char* s)
{ std::cout << s << std::endl; }
};
class B : public virtual A {
public:
B(const char* s1, const char* s2) : A(s1)
{ std::cout << s2 << std::endl; }
};
class C : public virtual A {
public:
C(const char* s1, const char* s2) : A(s1)
{ std::cout << s2 << std::endl; }
};
class D : public B, C {
public:
D(const char* s1, const char* s2, const char* s3, const char* s4)
: B(s1, s2), C(s3, s4), A(s1)
{
std::cout << s4 << std::endl;
}
};
int main(int argc, char* argv[])
{
D dobject("class A", "class B", "class C", "class D");
return 0;
}
由于B,C 为虚继承,实例化 B, C 对象时不会构造 A ,则打印为
class A
class B
class D
class D
参考链接
- CppReference
https://en.cppreference.com/w/cpp/language/derived_class