2

考虑以下无效的 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,这样它就可以ChildNodeChildNodeInterface. 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;
}

ParentNodeInterface但是,在和ChildNodeInterface都继承自的特殊情况下,NodeInterface就会出现歧义。从 中的断言中应该可以清楚地看出main,我的目标不是虚拟继承NodeInterface. 我打算对NodeInterface::fin进行真正不同的实现ParentNode。我想知道(如果可能的话)我如何区分ParentNodeInterface::fChildNodeInterface::fin的实现ParentNode

4

2 回答 2

1

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

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

C++ 不允许重新定义具有相同签名的函数两次。因此无法编写相同虚函数的 2 个实现。

所以你有2个选择:

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

    virtual int f (const int& n) const { return 3*n + mChild->f(n); 但我不知道这是否是你想要的行为。

于 2012-08-23T07:56:16.023 回答
1

请注意,ChildNodeInterface确实与ChildNode::f().

但是要解决您的问题(我认为),而不是私下继承 from ,而是使用继承自该类型并覆盖该类型 ChildNodeInterface的辅助类型。可以维护指向其中一个对象的指针(或仅具有该类型的普通旧成员),并在调用时分配指向该对象的指针:ChildNodeChildNode::f()ParentNodeParentNode::GetChildHandle()

// the helper class
class ParentNode;
class ParentsChildNodeInterface : public ChildNode {
public:
    virtual int f (const int& n) const;
};

class ParentNode : public ParentNodeInterface {

public:
    explicit ParentNode () :
        mChild (new ParentsChildNodeInterface ())
    {
    }

    virtual ~ParentNode () {}

    ChildNodeInterface* GetChildHandle () {
        return mChild;
    }

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

private:
    ParentsChildNodeInterface* const mChild;
};

// the new, special f() for children of parents...
int ParentsChildNodeInterface::f (const int& n) const {
    return 1 + ChildNode::f (n);
}

正如所发布的,帮助类不需要访问ParentNode对象中的任何状态。但是,如果确实需要,您可以将助手类设为friend.ParentNode

于 2012-08-23T08:16:45.263 回答