다음 잘못된 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;
}
는 ChildNodeInterface
의 ChildNode
의 구현의 상단에 몇 가지 추가 기능을 추가 할 수 있도록, ParentNode
비공개 적 ChildNode
처럼 보이게하는 나의 목표이다. 따라서 ParentNode
은 GetChildHandle
이라는 단순성으로 표시된 변장의 ChildNode
핸들로 효과적으로 처리 될 수 있습니다. 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::f
의 고유 한 구현을 ParentNode
에 사용하고자합니다. 가능하면 ParentNodeInterface::f
과 ChildNodeInterface::f
의 구현을 ParentNode
에 어떻게 구별 할 수 있는지 궁금합니다.
"동일한 서명으로 함수를 두 번 재정의하는 것은 C++에서 허용되지 않습니다"라고 말합니다. 나는 동의한다, 그러나 나는 왜이 가상이 정확하게 동일한 서명을 가지고 있는지 이해하지 못한다. 'ParentNode'에서 볼 수 있듯이'f'는 public과 private (차이점)과 ChildNodeInterface 또는 ParentNodeInterface (또 다른 차이점)를 통해 발생합니다. – Krokeledocus
내가 아는 한 가시성은 서명의 일부가 아닙니다. ParentNode 관점에서 가시성은 동일합니다. 다이아몬드 상속과 더불어, 컴파일러는 어느 상속 경로에서 프로토 타입을 얻을 수 있는지 알 수 없기 때문에 일반적인 기반에서 가상 함수를 재정의 할 수 없습니다. 가상 상속을해야만 이런 종류의 일을 할 수 있습니다. –