grundoperation +,-,*,/ in basisklasse
-
hallo,
ich habe bei meinen klassen festgestellt, dass viele mit den besagten operatoren arbeiten und das prinzip bei deren definition/deklaration immer das gleiche ist. als beispiel für einen +/- operator folgendes.template<class t> class cadd{ public: virtual t &add(const t &src) = 0; virtual t negate() const = 0; t &operator += (const t &src) { return add(src); }; t &operator -= (const t &src) { return add(src.negate()); }; t &operator *= (int n) { //quasi n mal sich selbst aufaddieren }; t operator - () const { return src.negate(); }; }; t operator + (cadd<t> const &lhs, t const & rhs) { cadd<t> l(lhs); //problem return l += rhs; }; t operator - (cadd<t> const &lhs, t const & rhs) { return lhs + rhs.negate(); }; t operator * (cadd<t> const &lhs, int rhs) { cadd<t> l(lhs); //problem return l *= rhs; };analog kann man sowas auch noch für die * und / operatoren machen. mein ziel ist die redundanz im code zu vermeiden, da man ja letztendes doch immer wieder das gleiche aufschreibt. so wie es jetzt dasteht geht es jedenfalls nicht, da bekommt man diverse fehlermeldungen z.B. das bei "//problem" im code eine abstrakte klasse nicht instanziert werden kann, was ja auch klar ist.
wenn jemand eine idee hat oder mir sagen kann warum das nicht gehen kann, wäre ich sehr dankbar.
-
Wenn du cadd und die abgeleiteten Typen für die du die operatoren implementieren willst, in einem eigenen Namespace untergebracht hast, geht das relativ einfach mit einem template:
namespace caddspace { template<class t> class cadd{ /*...*/}; //abgeleitete Klassen... template <class LHS_t, class t> t operator+(LHS_t const& lhs, t const& rhs) { LHS_t l(lhs); l += rhs; return l; } }Im globalen Namespace ists natürlich nicht gut, so einen templateoperator zu definieren, da der dann alles versucht, zusammenzuaddieren, wo nur ein "+" zwischen steht. Da der operator aber innerhalb des namespace deklariert ist, wird er nur in Betracht gezogen, wenn der Compiler innerhalb den namespace nach dem Operator sucht. Das wiederum geschieht nur, wenn man den namespace direkt angibt (also explizit
caddspace::operator+(a,b)schreibt), oder wenn durch Koenig-Lookup in dem Namespace nach einem geeigneten Operator gesucht wird - Koenig Lookup bedeutet, dass der Compiler in den Namespaces, aus denen die operanden stammen, nach geeigneten Operatoren schaut. In dem Fall wird der op also dann gefunden, wenn einer der operanden im namespace caddspace ist.
-
ich hab das jetzt mal so probiert, mit dem namespace, aber leider bekomme ich folgende fehlermeldungen:
//im header-file namespace caddspace { //... template<class lhs_t, class t> t operator + (class lhs_t const &lhs, t const &rhs); } //in cpp-file using namespace caddspace; template<class lhs_t, class t> t operator + (class lhs_t const &lhs, t const &rhs) { lhs_t ret(lhs); return ret += rhs; };error C2649: 'typename' : is not a 'class' error C2988: unrecognizable template declaration/definition error C2059: syntax error : '<end Parse>'
-
Templates werden grundsätzlich in den Headern vollständig definiert, da sie speziell gelinkt werden (für jede Typ-Instanziierung eines Templates wird schlussendlich eine eigene Funktion oder Klasse erstellt).
-
deswegen include ich die cpp.datei ja auch in der header datei, ich wollte das halt nur trennen
-
keine using-direktive in die cpp sondern die operatoren die du definierst qualifizieren:
template<class lhs_t, class t> t caddspace::operator + (class lhs_t const &lhs, t const &rhs) { lhs_t ret(lhs); return ret += rhs; };Unterscheidet sich nicht besonders von Klassenmethoden...
-
betsen dank jetzt funktioniert alles

-
mein ziel ist die redundanz im code zu vermeiden
Um das zu tun, kannst du auch mal einen Blick in boost::operator werfen.

Kann durchaus nützlich sein. Vor allem, wenn du keine Lust hast alle möglichen Operatoren zu definieren.