有没有一种方法来转发申报协方差?
-
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 ::酒吧为模板,后来边界允许你解决这个问题。
这个怎么样。
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