Duplizierter Unterklasse der abstrakten Basisklasse
-
28-10-2019 - |
Frage
Ich habe eine abstrakte Basisklasse, um einige Unterklassen durchzusetzen, um den << Operator zu überladen.
Ich speichere ein paar Zeiger für Fälle dieser Unterklassen in einem std :: stapel ... irgendwann möchte ich das obere Element des Stapels duplizieren (und darüber drücken).
Das Problem ist, dass ich keine abstrakte Klasse instanziieren kann. Und natürlich, da ich dies für jede meiner Unterklassen tun möchte, werde ich den Typ nicht wissen ...
Ich frage mich, ob dies auch möglich ist, ohne eine andere reine virtuelle Methode hinzuzufügen (sagen wir 'Basis *Clone () = 0') und implementieren Sie sie in jeder meiner Unterklassen. Sicherlich muss es einen saubereren Weg geben.
Lösung
Ich denke du brauchst tatsächlich eine Clone
Methode in diesem Fall. Sie möchten das Subklasselement zur Laufzeit dynamisch kopieren, und die normale Möglichkeit, das Verhalten zur Laufzeit zu ändern, sind virtuelle Methoden. Ohne eine virtuelle Methode hätten Sie keine Möglichkeit, herauszufinden, welches Kind es ist. Sie könnten wahrscheinlich CRTP verwenden, um diesen Klon automatisch für Sie zu generieren:
// Totally uncompiled and untested.
class Base
{
public:
virtual Base* Clone() const = 0;
};
template <class T>
class Child : public Base
{
public:
virtual Base* Clone() const { return new T(*static_cast<T*>(this)); }
protected:
Child(); // Can't instantiate directly
Child(const Child& right); // Can't instantiate directly
};
class Grandchild : public Child<Grandchild>
{
// Clone should do the right thing.
};
Andere Tipps
Meinen Sie eine Kopie der Klasse, anstatt den Zeiger zu duplizieren?
Sie müssen entweder Ihr eigenes Tippen implementieren. Mit anderen Worten haben eine virtuelle Funktion, die den Klassentyp zurückgibt und dann die entsprechende Klasse erstellt
Oder aktivieren Sie RTTI (Laufzeitinformationen), um dasselbe zu tun. Denn RTTI bewirkt jede Klasse, ist möglicherweise effizienter, um Ihre eigene Typenmethode zu erstellen.
Dann kannst du
- Pop den Zeiger
- Holen Sie sich den Typ
- Instantieren Sie die richtige Klasse mit einem Kopierkonstruktor wahrscheinlich in einem Switch
- Schieben Sie beide zurück auf den Stapel
PSUDOCODE
base* ptr = stack.pop()
base *copy
switch (ptr->typeof()) {
case class1type : copy = new class1(ptr) break;
case class2type : copy = new class2(ptr) break;
...
}
stack.push (ptr)
stack.push(copy)
DC