Frage

Angenommen, ich habe diese abstrakten Klassen Foo und Bar:

class Foo;
class Bar;

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

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

weiter Nehmen wir an, ich die abgeleitete Klasse ConcreteFoo und ConcreteBar haben. Ich möchte kovariant den Rückgabetyp der wie folgt foo() und bar() Methoden verfeinern:

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

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

Dies wird nicht kompiliert, da unser geliebter Single-Pass-Compiler nicht weiß, dass ConcreteBar von Bar erben wird, und so, dass ConcreteBar ist ein völlig legaler kovarianten Rückgabetyp. Plain nach vorn erklärt ConcreteBar nicht, entweder nicht funktioniert, da es nicht den Compiler etwas über die Vererbung nicht sagen.

Ist das ein Manko von C ++ Ich werde mit leben müssen, oder ist es tatsächlich ein Weg, um dieses Dilemma?

War es hilfreich?

Lösung

Sie können gefälschte es ganz leicht, aber Sie verlieren die statische Typprüfung. Wenn Sie die dynamic_casts durch static_casts ersetzen Sie, was der Compiler intern verwendet, aber Sie haben keine dynamische noch statische Typprüfung:

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

Andere Tipps

Nicht statischer Polymorphismus Ihr Problem lösen? Die Fütterung der Basisklasse mit der abgeleiteten Klasse durch Template-Argument? So ist die Basisklasse wird die Ableitung Typ kennen und eine richtige virtuelle erklären?

Kovarianz basiert auf Vererbung Diagramm, so da man nicht erklären kann

class ConcreteBar : public Bar;

daher keine Möglichkeit, Compiler über Kovarianz zu erzählen.

Aber man kann es mit Hilfe von Vorlagen tun, erklären ConcretFoo :: bar als Vorlage und später Begrenzungs ermöglicht es Ihnen, dieses Problem lösen

Wie wäre es diese.

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();
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top