Ich hätte gerne mehrere Typen, die dieselbe Implementierung verwenden, aber in C ++ immer noch vom unterschiedlichen Typ sind.
Um meine Frage anhand eines einfachen Beispiels zu veranschaulichen, hätte ich gerne eine Klasse für Äpfel, Orangen und Bananen, die alle die gleichen Operationen und die gleiche Implementierung haben. Ich möchte, dass sie unterschiedliche Typen haben, weil ich Fehler aufgrund der Typensicherheit vermeiden möchte.
class Apple {
int p;
public:
Apple (int p) : p(p) {}
int price () const {return p;}
}
class Banana {
int p;
public:
Banana (int p) : p(p) {}
int price () const {return p;}
}
class Orange ...
Um Code nicht zu duplizieren, könnte ich anscheinend eine Basisklasse Fruit verwenden und davon erben:
class Fruit {
int p;
public:
Fruit (int p) : p(p) {}
int price () const {return p;}
}
class Apple: public Fruit {};
class Banana: public Fruit {};
class Orange: public Fruit {};
Aber dann werden die Konstruktoren nicht geerbt und ich muss sie neu schreiben.
Gibt es einen Mechanismus (Typedefs, Vorlagen, Vererbung ...), mit dem ich problemlos dieselbe Klasse mit unterschiedlichen Typen haben kann?
Antworten:
Eine übliche Technik besteht darin, eine Klassenvorlage zu haben, bei der das Vorlagenargument einfach als eindeutiges Token („Tag“) dient, um es zu einem eindeutigen Typ zu machen:
Beachten Sie, dass die Tag-Klassen nicht einmal definiert werden müssen. Es reicht aus , einen eindeutigen Typnamen zu deklarieren . Dies funktioniert , weil der Tag ISN tatsächlich verwendet überall in der Vorlage. Und Sie können den Typnamen in der Liste der Vorlagenargumente deklarieren (Tipp an @Xeo).
Die
using
Syntax lautet C ++ 11. Wenn Sie mit C ++ 03 nicht weiterkommen, schreiben Sie stattdessen Folgendes:Wenn die allgemeine Funktionalität viel Code beansprucht, führt dies leider ziemlich viel doppelten Code in die endgültige ausführbare Datei ein. Dies kann verhindert werden, indem eine gemeinsame Basisklasse die Funktionalität implementiert und dann eine Spezialisierung (die Sie tatsächlich instanziieren) hat, die sich daraus ableitet.
Leider müssen Sie dazu alle nicht vererbbaren Mitglieder (Konstruktoren, Zuweisungen…) erneut implementieren, was selbst einen geringen Overhead verursacht. Dies ist also nur für große Klassen sinnvoll. Hier wird es auf das obige Beispiel angewendet:
quelle
Fruit<struct SomeTag>
.Verwenden Sie Vorlagen und ein Merkmal pro Frucht, zum Beispiel:
Dann haben Sie eine einzelne
Fruit
Klasse, die auf diesem Merkmal eingegeben wird, z.Kann etwas übertrieben sein! ;)
quelle
template<class Derived> class Fruit;
quelle
Es gibt auch BOOST_STRONG_TYPEDEF .
quelle