請考慮以下無效的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;
}
然而,在特殊情況下ParentNodeInterface
和ChildNodeInterface
無論從NodeInterface
繼承,歧義發生。 從main
的說法應該清楚,我不打算虛擬繼承NodeInterface
。我打算在ParentNode
中實現NodeInterface::f
的真正獨特實現。 我不知道如何(如果可能)我可以區分ParentNodeInterface::f
和ChildNodeInterface::f
ParentNode
的實施。
你說「C++不允許使用相同的簽名重新定義兩次函數」。我同意,但我不明白爲什麼這些虛擬機具有完全相同的簽名。正如從'ParentNode'看到的,'f'在公共和私有(這是一個區別)以及通過'ChildNodeInterface'或'ParentNodeInterface'(這是另一個區別)。 – Krokeledocus
據我所知,知名度不是簽名的一部分。在ParentNode的觀點中,可見性是相同的。除了菱形繼承之外,由於編譯器無法知道原型的繼承路徑是什麼,所以不能從公共基礎重新定義虛擬函數。你必須做虛擬繼承才能做這種事 –