Question

Supposons que j'ai ces classes abstraites Foo et Bar:

class Foo;
class Bar;

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

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

On suppose en outre que je la classe dérivée ConcreteFoo et ConcreteBar. Je veux raffiner covariante le type de retour des méthodes de foo() et bar() comme ceci:

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

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

Ce ne compilera pas depuis notre compilateur monopasse bien-aimé ne sait pas que ConcreteBar va hériter de Bar, et que ConcreteBar est un type de retour covariant parfaitement légal. Plaine déclarant avant ConcreteBar ne fonctionne pas non plus, car il ne dit pas quoi que ce soit du compilateur sur l'héritage.

Est-ce un défaut de C ++ Je vais devoir vivre avec ou est-il réellement un moyen de contourner ce dilemme?

Était-ce utile?

La solution

Vous pouvez simuler assez facilement, mais vous perdez le contrôle de type statique. Si vous remplacez la dynamic_casts par static_casts, vous avez ce que le compilateur utilise en interne, mais vous avez pas de vérification de type dynamique ni statique:

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

Autres conseils

Ne polymorphisme statique résoudre votre problème? L'alimentation de la classe de base avec la classe dérivée par un argument de modèle? Ainsi, la classe de base va connaître le type dérivé et déclarer? Virtuelle appropriée

Covariance est basé sur l'héritage diagramme, donc, puisque vous ne pouvez pas déclarer

class ConcreteBar : public Bar;

donc aucun moyen de dire compilateur sur la covariance.

Mais vous pouvez le faire avec l'aide de modèles, déclarer ConcretFoo :: barre en tant que modèle et englobante plus tard, vous permet de résoudre ce problème

Qu'en est-ce.

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();
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top