c++ - 如何消除重复继承的基类中重写虚拟变量的歧义?

标签 c++ multiple-inheritance

考虑以下无效的 C++ 代码。

#include <assert.h>

class NodeInterface {
public:
    virtual ~NodeInterface () {}

    virtual int f (const int& n) const = 0;
};

class ChildNodeInterface : public NodeInterface {
public:
    virtual ~ChildNodeInterface () {}
};

class ParentNodeInterface : public NodeInterface {
public:
    virtual ~ParentNodeInterface () {}
};

class ChildNode : public ChildNodeInterface {
public:
    virtual ~ChildNode () {}

    virtual int f (const int& n) const {
        return 2*n;
    }
};

class ParentNode : public ParentNodeInterface, private ChildNodeInterface {
public:
    explicit ParentNode () :
        mChild (new ChildNode ())
    {
    }

    virtual ~ParentNode () {}

    ChildNodeInterface* GetChildHandle () {
        return this;
    }

    virtual int f (const int& n) const {
        return 3*n;
    }

private:
    ChildNode* const mChild;

    // How do I specify that I would like to override ChildNodeInterface::f?
    virtual int f (const int& n) const { // On MSVC2010: C2535 member function already defined or declared
        return 1 + mChild->f (n);
    }
};

int main()
{
    ParentNode parent;
    assert (parent.f (2) == 6);
    ChildNode node;
    assert (node.f (2) == 4);
    ChildNodeInterface* child (parent.GetChildHandle ());
    assert (child->f (2) == 5);
    return 0;
}

我的目标是让 ParentNode 私下看起来像 ChildNode,这样它就可以在 ChildNode 之上添加一些附加功能” ChildNodeInterface 的实现。因此,ParentNode 可以有效地被视为变相的 ChildNode 句柄,这由 GetChildHandle 的简单性表明。 显然,如果ParentNode不会重复继承NodeInterface,就不会有问题。这样一来,人们就可以轻松地消除覆盖的歧义。下面的正确示例说明了这一点:

#include <assert.h>

class ChildNodeInterface {
public:
    virtual ~ChildNodeInterface () {}

    virtual int ChildMethod (const int& n) const = 0;
};

class ParentNodeInterface {
public:
    virtual ~ParentNodeInterface () {}

    virtual int ParentMethod (const int& n) const = 0;
};

class ChildNode : public ChildNodeInterface {
public:
    virtual ~ChildNode () {}

    virtual int ChildMethod (const int& n) const {
        return 2*n;
    }
};

class ParentNode : public ParentNodeInterface, private ChildNodeInterface {
public:
    explicit ParentNode () :
        mChild (new ChildNode ()),
        mValue (1)
    {
    }

    ChildNodeInterface* GetChildHandle () {
        return this;
    }

    virtual int ParentMethod (const int& n) const {
        return 3*n;
    }

private:
    ChildNode* const mChild;
    const int mValue;

    virtual int ChildMethod (const int& n) const {
        return mValue + mChild->ChildMethod (n);
    }
};

int main()
{
    ParentNode parent;
    assert (parent.ParentMethod (2) == 6);
    ChildNode node;
    assert (node.ChildMethod (2) == 4);
    ChildNodeInterface* child (parent.GetChildHandle ());
    assert (child->ChildMethod (2) == 5);
    return 0;
}

但是,在 ParentNodeInterfaceChildNodeInterface 都继承自 NodeInterface 的特殊情况下,就会出现歧义。 从 main 中的断言可以清楚地看出,我的目标不是 NodeInterface 的虚拟继承。我的目的是在 ParentNode 中拥有真正不同的 NodeInterface::f 实现。 我想知道如何(如果可能)区分 ParentNodeInterface::fChildNodeInterface::fParentNode 中的实现。

最佳答案

我认为你的设计是错误的。您继承了 ChildNodeInterface 并且您的 ParentNode 类中有一个 ChildNode 成员?

Inherited ChildNodeInterface 不允许您使用 f 函数实现,因为 ChildNode 类不在继承树中。

C++ 不允许对具有相同签名的函数进行两次重新定义。因此编写同一个虚函数的 2 个实现是不可能的。

所以你有两个选择:

  1. [最佳] 尝试以正确的方式使用继承重新定义类设计。菱形继承(钻石问题)通常是由于糟糕的设计造成的。
  2. [最快]从 ChildNodeInterface 中删除继承,并更喜欢在 ParentNode::f() 函数中调用 mChild->f() 来将 Child 行为添加到父节点:

    虚拟 int f (const int& n) const { 返回 3*n + mChild->f(n); } 但我不知道这是否是您想要的行为。

关于c++ - 如何消除重复继承的基类中重写虚拟变量的歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12086777/

相关文章:

c++ - QGraphicsItem 边框样式

c++ - QScintilla - 在自定义词法分析器中为单词添加颜色

python - 菱形继承(钻石问题) - 多重继承 python - 只调用一次方法 - 但如何呢?

c++ - 在 QPlainTextEdit 中获取指向 QTextBlock 的指针

c++ - 使用重载运算符不明确

c++ - 为什么在可怕的菱形情况下需要父类(super class)空构造函数但不调用?

c++ - 如何从多个继承的类对象中分配 unique_ptr<base>?

c++ - 多重继承方便吗?

C++ 调用 - 搜索功能

python - 向内置类型的多重继承子类的构造函数添加可选参数?