抽象类的多重继承导致定义不明确

Posted

技术标签:

【中文标题】抽象类的多重继承导致定义不明确【英文标题】:Multiple inheritance of abstract class results in ambiguous definition 【发布时间】:2020-09-16 06:51:58 【问题描述】:

我正面临我根导致此代码 sn-p 的继承层次结构错误。 l() 的定义是在模板类 Y 中定义的,我不明白为什么编译器会发现它模棱两可。Class Z ptr_ 指向具有 l() 定义的 Y 类对象,这不是应该的吗工作吗?

不幸的是,基类都是静态库的一部分,C 类是我唯一可以控制的东西。我不确定我能在这里做什么。

Error:
Line 84: Char 13: error: non-static member 'l' found in multiple base-class subobjects of type 'D':
    class C -> class A -> class D
    class C -> class B -> class D
      ptr_->l ()

Line 96: Char 15: note: in instantiation of member function 'Z<C>::~Z' requested here
  Z < C > t = new Y < C > ();
              ^

Line 31: Char 16: note: member found by ambiguous name lookup
  virtual void l () = 0;
#include <iostream>

using namespace std;

template <class T> 
class Y : public T 
public:
  void l() 
  void p() 
;

class D 
public:
  virtual void l() = 0;
  virtual void p() = 0;
;

class A : public D 
public:
  virtual void f(int a) = 0;
  virtual void d() = 0;
;

class B : public D 
public:
  virtual void j(string x) = 0;
  virtual void d() = 0;
;

class C : public A, public B 
public:
  void f(int a) override 

  void j(string x) override 

  void d() override 
;

template <class T> 
class Z 
public:
  Z(T *ptr) : ptr_(ptr) 

  ~Z() 
    if (ptr_)
      ptr_->l();
  

protected:
  T *ptr_;
;

int main() 

  Z<C> t = new Y<C>();

  return 0;



【问题讨论】:

class C 继承自 class Aclass B。因此,它公开了两个virtual 方法l()A::l()B::l()。因此,编译无法决定为ptr_-&gt;l(); 选择哪一个。使用 virtual 基类或帮助它(通过插入强制转换)来选择预期的。 这是因为C 通过两个不同的路径(如A::l()B::l())继承了成员函数l()。两者都解析为 D::l() 的事实是无关紧要的 - 有两条不同的路径可以到达它,没有理由偏爱一条或另一条,也没有什么能阻止 AB提供自己的覆盖。修复选项(没有修复继承关系以消除歧义,这通常是更可取的)是命名您想要的(例如ptr-&gt;A::l()ptr-&gt;B::l())或使D 成为A 的虚拟基础和B. 仅供参考:SO: In C++, what is a virtual base class? 不幸的是,基类都是静态库的一部分,C 类是我唯一可以控制的东西。我不确定我能在这里做什么。 【参考方案1】:

您的问题是您的继承层次结构如下所示:

  C
 / \
A   B
|   |
D   D   <- Defines l()

所以当你通过C 类型调用l() 时,编译器不知道你是想调用C::A::D::l() 还是C::B::D::l()

解决此问题的一种方法是在 C 类中指定您实际要使用的分支。

编译器在您的示例中抱怨因为l()D 中是抽象的,但是如果在您的“真实”代码中不是这种情况,那么这可以解决歧义:

class C : public A, public B 
public:
    ...
    virtual void l() override  A::l();  // Or B::l() if you prefer, of course
;

但如果l()D 中是抽象的,并且在AB 中没有实现,那么您可以在C 中执行此操作:

class C : public A, public B 
public:
    ...
    virtual void l() = 0;
;

【讨论】:

对此的小补充:如果您可以将系统设计为在没有多重继承的情况下工作,那么您应该认真考虑这样做。多重继承是一个强大的工具,但它在幕后也相当复杂,而且很容易遇到奇怪的情况,即事情不能像你期望的那样工作。

以上是关于抽象类的多重继承导致定义不明确的主要内容,如果未能解决你的问题,请参考以下文章

来自两个抽象类的多重继承 (Qt)

Java复习笔记4--实现多重继承

Django:从带有元的抽象类的多重继承

12:抽象类,接口,多重继承

CDI:由于多重继承和泛型抽象导致的属性注入问题

多继承 与 多重继承