Gibt es eine Möglichkeit declare Kovarianz zu übermitteln?
-
12-09-2019 - |
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?
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();
};