首页 > 解决方案 > 非抽象但无状态的类对于多重继承是否与纯抽象类一样安全?

问题描述

在大多数书籍和文章中,进行多重继承的唯一“安全”(或至少是唯一建议的)方法是使用纯抽象基类(您可以称为虚拟接口)的虚拟继承。

原因主要是为了避免钻石问题,在这种问题中,数据成员的价值或非纯虚函数的实现状态可能会产生歧义。

纯抽象基类不会同时受到两者的影响(没有数据成员,没有非纯虚拟),虚拟继承甚至解决了基类实际内存地址的歧义。

但是给出这样的解释:如果歧义仅来自“状态”的形式(例如数据成员,静态函数变量),那么无状态的非抽象(甚至可能使用所有“最终”方法)类不是同样安全的是多重继承层次结构中的基类?

我错过了什么可能的问题?

PS:如果答案是“如果没有虚拟方法,那么无论如何你都可以使用组合”:除了学术兴趣之外,我有一个案例,我需要成员函数的属性才能能够无阴影,全局 C-样式函数,因此我无法通过指向组合对象的指针访问它们。

标签: c++virtualabstract

解决方案


虚拟继承通过避免非静态成员的重复副本已经实现了所需的安全性。变量和函数在这方面是一样的:即使基类是无状态的,如果它不止一次是基类,它的非静态成员函数也是模棱两可的。

虚拟继承还可以智能地处理覆盖:

struct B {
  virtual ~B()=default;
  virtual void f()/*=0*/;
};
struct X : virtual B {};
struct Y : virtual B {
  void f() override;
};
struct D : X,Y {};

B& b();
void g() {
  b().f();    // calls Y::f
}

是否B::f是纯虚拟的并不重要。

所以无国籍不是重要的部分。此外,如果基础是无状态的,拥有final成员将阻止默认存根实现的最明显用例。(唯一this另一种可能性是取决于好主意)。

所以你是正确的,非纯虚拟函数可以是安全的,但即使基础是有状态的也是如此。当然,多重继承的安全性仍然存在限制,例如重载集接受多个直接基时的歧义。


推荐阅读