공분산 선언을 전달하는 방법이 있습니까?
-
12-09-2019 - |
문제
이 추상 수업이 있다고 가정 해 봅시다 Foo
그리고 Bar
:
class Foo;
class Bar;
class Foo
{
public:
virtual Bar* bar() = 0;
};
class Bar
{
public:
virtual Foo* foo() = 0;
};
더 파생 된 수업이 있다고 가정 해 봅시다 ConcreteFoo
그리고 ConcreteBar
. 나는 반환 유형의 foo()
그리고 bar()
이와 같은 방법 :
class ConcreteFoo : public Foo
{
public:
ConcreteBar* bar();
};
class ConcreteBar : public Bar
{
public:
ConcreteFoo* foo();
};
우리의 사랑하는 단일 패스 컴파일러가 ConcreteBar
상속 될 것입니다 Bar
, 그리고 그렇게 ConcreteBar
완벽하게 합법적 인 공분산 반환 유형입니다. 평범한 전진 선언 ConcreteBar
컴파일러에게 상속에 대해 아무것도 말하지 않기 때문에 작동하지 않습니다.
이것은 C ++의 단점입니까?
해결책
당신은 그것을 아주 쉽게 가짜로 만들 수 있지만 정적 유형 검사를 잃습니다. 당신이 교체하는 경우 dynamic_casts
~에 의해 static_casts
, 컴파일러가 내부적으로 사용하는 것을 가지고 있지만 동적 또는 정적 유형 점검은 없습니다.
class Foo;
class Bar;
class Foo
{
public:
Bar* bar();
protected:
virtual Bar* doBar();
};
class Bar;
{
public:
Foo* foo();
public:
virtual Foo* doFoo();
};
inline Bar* Foo::bar() { return doBar(); }
inline Foo* Bar::foo() { return doFoo(); }
class ConcreteFoo;
class ConcreteBar;
class ConcreteFoo : public Foo
{
public:
ConcreteBar* bar();
protected:
Bar* doBar();
};
class ConcreteBar : public Bar
{
public:
ConcreteFoo* foo();
public:
Foo* doFoo();
};
inline ConcreteBar* ConcreteFoo::bar() { return &dynamic_cast<ConcreteBar&>(*doBar()); }
inline ConcreteFoo* ConcreteBar::foo() { return &dynamic_cast<ConcreteFoo&>(*doFoo()); }
다른 팁
정적 다형성이 당신의 문제를 해결하지 않습니까? 템플릿 인수를 통해 파생 클래스로 기본 클래스를 공급합니까? 기본 클래스는 파생 유형을 알고 적절한 가상을 선언 할 것입니까?
공분산은 상속 다이어그램을 기반으로하므로 선언 할 수 없기 때문에
class ConcreteBar : public Bar;
따라서 공분산에 대해 컴파일러에게 알리는 방법은 없습니다.
그러나 템플릿의 도움으로 할 수 있고, Concretfoo :: Bar를 템플릿으로 선언하고 나중에 경계를 낼 수 있습니다.이 문제를 해결할 수 있습니다.
이건 어때.
template <class BarType>
class Foo
{
public:
virtual BarType* bar() = 0;
};
template <class FooType>
class Bar
{
public:
virtual FooType* foo() = 0;
};
class ConcreteBar;
class ConcreteFoo : public Foo<ConcreteBar>
{
public:
ConcreteBar* bar();
};
class ConcreteBar : public Bar<ConcreteFoo>
{
public:
ConcreteFoo* foo();
};
제휴하지 않습니다 StackOverflow