有没有办法转发声明协方差?

Tob*_*ias 15 c++ covariance forward-declaration

假设我有这些抽象类,Foo并且Bar:

class Foo;
class Bar;

class Foo
{
public:
  virtual Bar* bar() = 0;
};

class Bar
{
public:
  virtual Foo* foo() = 0;
};
Run Code Online (Sandbox Code Playgroud)

进一步假设我有派生类ConcreteFooConcreteBar.我想协同改进foo()和这样的bar()方法的返回类型:

class ConcreteFoo : public Foo
{
public:
  ConcreteBar* bar();
};

class ConcreteBar : public Bar
{
public:
  ConcreteFoo* foo();
};
Run Code Online (Sandbox Code Playgroud)

这将无法编译,因为我们心爱的单通道编译器不知道ConcreteBar将继承Bar,因此这ConcreteBar是一个完全合法的协变返回类型.普通的前向声明ConcreteBar也不起作用,因为它没有告诉编译器有关继承的任何信息.

这是C++的一个缺点,我将不得不忍受或者是否真的有办法解决这个难题?

APr*_*mer 5

你可以很容易地伪造它,但是你失去了静态类型检查。如果您替换dynamic_castsby 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()); }
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案有效,但肯定不会赢得选美比赛:) (2认同)
  • @Tobias:我认为具有复杂依赖关系的原始设计也不会赢得选美比赛。:P (2认同)