Domanda

Supponiamo che io ho queste classi astratte Foo e Bar:

class Foo;
class Bar;

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

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

Si supponga, inoltre, che ho la classe ConcreteFoo e ConcreteBar derivata. Voglio perfezionare covariantly il tipo di ritorno dei metodi foo() e bar() come questo:

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

class ConcreteBar : public Bar
{
public:
  ConcreteFoo* foo();
};

Questo non sarà compilato dal nostro amato compilatore unico passaggio non sa che ConcreteBar erediterà da Bar, e in modo che ConcreteBar è un tipo di ritorno covariante perfettamente legale. Plain avanti dichiarando ConcreteBar non funziona, sia, dal momento che non dice nulla circa compilatore eredità.

Si tratta di una lacuna di C ++ dovrò vivere con o c'è in realtà un modo per aggirare questo dilemma?

È stato utile?

Soluzione

Si può fingere abbastanza facilmente, ma si perde il controllo di tipo statico. Se si sostituisce il dynamic_casts da static_casts, è avere quello che il compilatore sta usando internamente, ma non avete né dinamica statica di controllo Tipo:

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()); }

Altri suggerimenti

Non polimorfismo statico risolto il problema? Nutrire la classe di base con la classe derivata attraverso argomento di template? Quindi la classe di base si conosce il tipo derivato e dichiarare una corretta virtuale?

covarianza si basa sullo schema di successione, quindi dal momento che non è possibile dichiarare

class ConcreteBar : public Bar;

quindi c'è modo di dire compilatore su covarianza.

Ma si può fare con l'aiuto di modelli, dichiarare ConcretFoo :: bar come modello e di delimitazione poi permette a risolvere questo problema

Che ne dite di questo.

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();
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top