抽象类的多重继承导致定义不明确
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 A
和 class B
。因此,它公开了两个virtual
方法l()
:A::l()
和B::l()
。因此,编译无法决定为ptr_->l();
选择哪一个。使用 virtual 基类或帮助它(通过插入强制转换)来选择预期的。
这是因为C
通过两个不同的路径(如A::l()
和B::l()
)继承了成员函数l()
。两者都解析为 D::l()
的事实是无关紧要的 - 有两条不同的路径可以到达它,没有理由偏爱一条或另一条,也没有什么能阻止 A
或 B
提供自己的覆盖。修复选项(没有修复继承关系以消除歧义,这通常是更可取的)是命名您想要的(例如ptr->A::l()
或ptr->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
中是抽象的,并且在A
或B
中没有实现,那么您可以在C
中执行此操作:
class C : public A, public B
public:
...
virtual void l() = 0;
;
【讨论】:
对此的小补充:如果您可以将系统设计为在没有多重继承的情况下工作,那么您应该认真考虑这样做。多重继承是一个强大的工具,但它在幕后也相当复杂,而且很容易遇到奇怪的情况,即事情不能像你期望的那样工作。以上是关于抽象类的多重继承导致定义不明确的主要内容,如果未能解决你的问题,请参考以下文章