具有相同名称的抽象和定义继承函数的多重继承

4

首先,如果已经有其他帖子回答了这个问题,我很抱歉,我找到的所有类似帖子都涉及到钻石继承方案或定义函数,而这个问题不是这样。

简而言之,我想知道是否可能让一个类从两个其他类继承,其中两个子类具有相同名称和参数的函数,但在一个子类中定义,在另一个子类中是纯虚函数。此外,如果我能做到这一点,调用抽象类上的函数是否会以最小的更改调用另一个子类中定义的函数?

例子:

class A
{
    public:
    virtual void Set(int X) = 0;
};

class B
{
    public:
    virtual void Set(int X);
};

class AB : public A, public B
{
    //other methods not relevant to example go here
};

int main(int argc, char **argv)
{
    int Y = 5;
    A* ObjectA = new AB();
    ObjectA->Set(Y);
    return 0;
}

到目前为止,我编译这个基本示例的尝试都遇到了错误,错误信息如下所示:
'AB':无法实例化抽象类,因为以下成员:'void A::Set(int)'是抽象的
在自己的研究中,我没有找到明确的答案,但根据其他涉及相关主题的问题,我发现在类AB中使用"using B :: Set"可能有助于解决这个问题。但当我尝试将其添加到AB类定义中时,错误仍然存在。
有没有办法让这个工作?

2
第四行缺少一个 virtual 关键字。 - Karl von Moor
你的代码至少缺少一个virtual修饰符,请修复。 - n. m.
现在我们知道为什么许多语言不实现MI,因为像你这样的人就一定要做这样的事情。 :) :) - Tony Hopkinson
@TonyHopkinson:这个问题与MI无关。提问者只是对纯虚函数感到困惑。 - Kerrek SB
修复了虚拟的问题。>.> - Mako_Energy
我以为标题表明了MI参与其中,更不用说菱形图案和内置的命名冲突了。哦,我真是太愚蠢了... - Tony Hopkinson
3个回答

2
如果你在类A和类B中都有两个普通函数Set,那么使用B::Set会告诉编译器,如果你有一个AB类的对象并调用该对象的Set方法,如果没有明确定义AB::Set,那么将调用B::Set。
但是你的情况不同。你有一个纯虚函数A::Set,这导致A成为抽象类。由于AB没有重写A::Set,AB也变成了抽象类,因此你不能实例化它。
在这里你可以实现AB::set来调用B::Set:
class AB : public A, public B
{
public:
    void Set(int x) { return B::Set(x); }
};

我不建议在基类中使用相同的方法名称,也不建议多重继承,尝试使用聚合代替。


0
你尝试过实现这个方法吗?
class AB : public A, public B
{
    void Set(int X) {}
};

原因是 A::Set() 是纯虚函数,即它没有实现。但你试图调用它。你必须在派生类中重写它,才能实例化派生类。
在你的情况下,using 不起作用,因为你有一个 A*,所以编译器没有歧义。
如果你有:
AB* ObjectA = new AB();
ObjectA->Set(Y);

你必须在AB的声明中使用using来解决歧义。


我曾经想过这样做,但是我希望有一个更精简的解决方案,因为我希望尽量减少将抽象类与其他类集成所涉及的代码。 在这种情况下,“AB”和“B”类可以是我的应用程序中的许多不同类。 尽管如此,如果这是我必须要做的,那就是我必须要做的。 如果没有更简洁的方法出现,我会接受这个答案。 谢谢。 - Mako_Energy
@Mako_Energy 不会有正确的答案告诉你如何实例化一个抽象类。由于您没有覆盖基本的抽象方法,您的类是抽象的。这方面没法绕过去。 - Luchian Grigore

0

Class AB 继承自 A,A 有一个纯虚方法使得该类成为抽象类,AB 必须 实现基类中声明的任何纯虚方法才能被实例化。

我会尽量避免多重继承,因为它可能会引起许多问题,通常有更好的方法来解决问题,例如在这个例子中,如果 B 共享并且实际上实现了与 A 相同的接口,那么 B 应该从 A 派生。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接