Operatoren auf typen zugeschnitten überladen
-
Hallo alle miteinander!
Ich würde gerne eine template klasse schreiben und in dieser operatoren überladen. die template klasse soll dabei hauptsächlich diverse strukturen als typ aufnehmen und mit diesen arbeiten. die Strukturdefinitionen sind alle bekannt.
kann ich nun für jede struktur z.b. den + operator speziell überladen?
wie würde die syntax dafür aussehen?ich kenne mich mit templates leider noch nicht so gut aus und hab leider meine c++ fibel nicht zur hand. per google finde ich leider gerade auch nichts was mir weiter helfen würde.
in dem sinne schon mal vielen dank!
der erik
-
Klar geht das.
Am besten schreibst du einfach freie Funktionen für die Operatoren, wie es hier empfohlen wird.
Die Mehrdeutigkeit wird dann per Überladung aufgelöst.Wenn die Funktion ein template sein soll, dann funktioniert das ganz analog dazu. Zeig doch mal was du hast!
-
Ok, ich habe zb. folgende beiden strukturen
struct idcst { int a,b; double d; char* st; }; struct bdst { bool on; double val };und möchte diese beiden in einer template klasse als typ nutzen
template <typename T> class dvec { private: T objekte; public: dvec(); bool operator+(bdst) { // implementierung bsdt + bdst return true; } };an sich ja nicht das problem. nur kann ich ja jetzt, wenn ich als templateparameter idcst angebe, eine bdst struktur hinzuaddieren was von der implementierung her aber nicht klappt wenn ich auf die einzelnen elemente der strukturen zugreife. und dies möchte ich gerne verhindern.
viele grüße!
-
Ich denke du bringst einiges durcheinander, denn ich verstehe die Frage überhaupt nicht. Auch solltest du schauen, wie man den +-Operator korrekt implementiert. Das findest du in dem Link, den ich oben gepostet habe.
Ein paar allgemeine Sachen:
Wenn du in dvec auf etwas von dem Template Parameter zugreifen möchtest, dann musst du ein einheitliches Interface dafür verlangen. Sonst gibt es Compile Time Fehler. Wenn du den Operator definierst weisst du ja den Typen des übergebenen Objektes und kannst dementsprechend darauf zugreifen. Und von dem Templateparameter musst du eben eine Schnittstelle erwarten, welche du dann einfach benutzt.
-
Ok, scheinbar hatte ich einen grundlegenden Denkfehler.
ich bin davon ausgegangen, dass die + - * / operatoren nur mit einem parameter überladen werden (rechter operant) und der linke operant durch this genutzt wird. da die operatoren aber ja 2 parameter übergeben bekommen werden dadurch ja auch die typen spezifiziert und meine frage ist damit verständlicherweise auch verwirrend und sinnlos.
nehmts mir nicht krumm, ich war wohl etwas verwirrt

gruß, der erik
-
Ok, da war ich wohl doch wieder etwas voreilig.
ich kann ja nicht einfach die beiden strukturen als parametertypen nehmen wenn ich mit klassen arbeite. Ok, ich hab mein problem noch mal kurz zusammenhängend niedergetippt:
struct idcst { int a,b; double d; char* st; }; struct bdst { bool on; double val }; template <class T> class dvec { private: T objekte*; protected: public: T& operator+(/* überladung für t = idcst */) { } T& operator+(/* überladung für t = bdst */) { } }; // aufruf //---------------------------------- dvec<idcst> a,b,c; dvec<bdst> x,y,z; c = a + b; // idcst + idcst -> ok z = x + y; // bdst + bdst -> ok a = b + x; // idcst + bdst -> fehler!ich habe also wieder meine beiden struktur typen. diese sollen der klasse dvec als templateparameter dienen.
in der klasse möchte ich nun den + operator überladen. einmal für den fall, dass idcst als templateparameter angegeben wurde und einmal wenn bdst als templateparameter angegeben wurde. es soll also möglich sein, klassen des selben templateparameter typs aufeinander zu addieren, jedoch nicht klassen unterschiedlichen templateparameter typs.
mein problem ist praktisch, dass ich nicht weis wie ich dem compiler sage, wann er welche operatorfunktion zu verwenden hat.
und entschuldigt bitte meine völlig falsche überladung im code im 2. post des threads. ist mir selbst auch etwas unerklärlich wieso ich dort solchen mist getippt habe

-
Dein Code ist nicht besser geworden. Lies den Link von drakon.
operator+ wird NICHT als Member einer Klasse definiert.
-
Ok, jetzt bin ich gerade völlig verwirrt.
Wieso wird operator+ nicht innerhalb der Klasse definiert? im Link von drakon steht unter 2.2., 2. absatz: "Die meisten Operatoren können sowohl als Methode einer Klasse als auch als freie Funktionen überladen werden, es gibt aber eine Handvoll Ausnahmen, die nur als Klassenmethoden überladen werden dürfen."
auch auf anderen seiten bin ich immer wieder über die überladung von operator+ innerhalb der klasse gestolpert.
ich will doch nur erreichen, dass nur instanzen der klasse dvec addiert werden können die den selben templateparametertyp besitzen und diese addition dann selbst implementieren
das kann doch eigentlich gar ne so schwer sein.
gruß, erik
-
Genau. Mach deine Operatoren zu globalen Templatefunktionen. Anschließend informierst du dich über "Templates spezialisieren", ich denke das ist es, was du suchst.
-
Hallo nochmals!
ich möchte die Operatoren jedoch nicht als globale Funktion implementieren sondern innerhalb der klasse. und das ist ja nun auch genau mein problem.
ist das innerhalb der klasse realisierbar, ja oder nein? wenn ja wäre ich über eine kleines implementierungsbeispiel von euch sehr dankbar.
gruß, der erik
-
Normalerweise implementiert man zuerst den Operator += innerhalb der Klasse und greift dann mit dem Operator +, welcher eine globale Funktion ist, auf den Operator += zu.
Wie man es richtig macht steht hier.
-
Terranigma schrieb:
ich möchte die Operatoren jedoch nicht als globale Funktion implementieren sondern innerhalb der klasse. und das ist ja nun auch genau mein problem.
Exakt, das ist dein Problem.
Warum willst du das?ist das innerhalb der klasse realisierbar, ja oder nein? wenn ja wäre ich über eine kleines implementierungsbeispiel von euch sehr dankbar.
Es ist möglich aber nicht sinnvoll.
-
Hallo ihr!
Das ganze soll innerhalb einer klasse gekapselt sein, da die klasse als dll breitgestellt werden soll.
wenn es möglich ist, könntet ihr mir doch bitte kurz ein kleines beipspiel posten.
Danke euch!
viele grüße, der erik
-
Terranigma schrieb:
Das ganze soll innerhalb einer klasse gekapselt sein, da die klasse als dll breitgestellt werden soll.
Und warum nicht die Funktion in der DLL bereitstellen?
Alles in Klassen packen ist eine üble Angelegenheit, die man hauptsächlich von Java-Programmierern kennt. Programmiere C++ so, wie es sinnvoll ist, sonst wird es sich früher oder später rächen.
-
Huhu!
Ok, ich will mich ja jetzt nicht beschweren und auch keine unnötige diskussion über die zweckmäßigkeit der implementierung inner- oder ausserhalb der klasse lostreten. ich hätte nur gerne ein kleines beispiel wie die implementierung aussieht, da ich selbst nirgends eine lösung finde. deshalb hoffe ich darauf noch eine antwort zu bekommen ohne ein für und wieder abzuwägen.
Danke:) grüße, der erik
P.S.: ich komme nicht aus dem java lager, und auch nicht von c#
ich hab schon immer c++ verwendet und fühl mich damit auch wohl 
-
Hauptsache nichts denken oder?

Und selbst suchen ist ja auch eine richtige Herausforderung. Erster Link:
http://lmgtfy.com/?q=c%2B%2B+operator+overloading
-
Hmm ich hab das gefühl, dass ich etwas missverstanden werde, und mich wohl etwas ungewählt ausgedrückt habe.
Ok, anders ausgedrückt:
Ich will nicht nur, dass die operatoren auf den rechten operanden spezialisiert überladen werden, sondern auch auf den linken.
es ist ja extern kein problem, z.b.
T operator+(dvec<idcst>& left,dvec<idcst>& right) { // implentierung } T operator+(dvec<bdst>& left,dvec<bdst>& right) { // implentierung }zu implementieren.
aber ich stoße an das problem, dass ich zb. die nachfolgenden beiden operatoren ja auch problemlos noch als externe funktion definieren kann, jedoch so nicht innerhalb der klasse
T operator+(dvec<idcst>& left,dvec<bdst>& right) { // implentierung } T operator+(dvec<bdst>& left,dvec<idcst>& right) { // implentierung }aber wie kann ich die ALLE in der klasse implementieren?
wenn ich die operatoren in der klasse implementiere, fehlt ja die typangabe des linken operators, und der compiler weis nicht welche funktion er nehmen soll zum addieren.aka: wie kann den compiler mitteilen, dass er anhand des templateparameters die richtige funktion wählt?
struct idcst { int a,b; double d; char* st; }; struct bdst { bool on; double val; }; template <class T> class dvec { private: T* objekt; protected: public: dvec() { objekt = new T[10]; } dvec& operator+(dvec<idcst>& right) // add1 , idcst+idcst { dvec<idcst> tmp; tmp.objekt->d = this->objekt->d + right.objekt->d; return tmp; } dvec& operator+(dvec<idcst>& right) // add2 , bdst+idcst { dvec<bdst> tmp; tmp.objekt->val = this->objekt->val + right.objekt->d; return tmp; } dvec& operator+(dvec<bdst>& rh) // add3 , idcst+bdst { dvec<idcst> tmp; tmp.objekt->d = this->objekt->d + rh.objekt->val; return tmp; } dvec& operator+(dvec<bdst>& rh) // add4 , bdst+bdst { dvec<bdst> tmp; tmp.objekt->val = this->objekt->val + rh.objekt->val; return tmp; } };add1 & add2 bzw. add3 und add4 sind hier von der parameterliste ja gleich, addieren aber unterschiedliche typen aufeinander. und dies möchte ich implementieren! ohne unterscheidung des templateparameters geht dies aber nicht, da die funktionen so ja für den compiler versucht werden neu zu definieren.
Wie kann ich dies implementieren, dass der compiler anhand des templateparameters z.b. korrekt zwischen add3 und add4 wählt?
Gruß, erik
-
Grundsätzlich finde ich es eine sehr schlechte Idee, die Addition nicht kommutativ zu machen. Oder welchen Typ willst du zurückgeben, wenn der linke Operand ein T und der rechte ein U ist? Du musst dich für einen entscheiden, wodurch a+b und b+a etwas ganz Anderes zurückgeben.
Nimm lieber benannte Funktionen, statt unintuitive Operatorüberladung zu erzwingen.
-
Nimm die Funktion.
Es gibt keinen Grund warum du es in die Klasse packen wollen wuerdest. Du hast damit nur die Probleme die du schon bemerkt hast. Das lohnt sich nicht darum herum zu arbeiten. Das ist einfach dumm.Ich denke du siehst in der freien Funktionen einen Nachteil den es nicht gibt. Du kannst es genausowenig in eine DLL packen wie wenn du es in die Klasse steckst. Klappt so oder so nicht.
Die Loesung waere konvertierungs Konstruktoren fuer die beiden Typen in deine Template Klasse zu packen. So dass bei
idcst + dvec<idcst>
der linke Operand zu einem dvec<idcst> mit einem Element wird und du den operator+(dvec,dvec) verwenden kannstIst aber baeh, deshalb: Freie Funktion.
Das ist wirklich die richtige Anwtort und nicht nur gesagt weils Cool ist. Sondern weil es wirklich die richtige Loesung fuer dein Problem ist. Alles andere ist pfusch.
-
hmm konvertierungs konstruktoren sind wirklich ne gerade schön.
Schade dass das nicht auch einfacher geht.
Aber hast recht, dass template in eine dll zu packen funktioniert natürlich nicht. ich wollte die klasse innerhalb einer dll verwenden. dies funktioniert aber mit den funktionen oder?
Gruß, erik
-
Wenn alle Typen bekannt sind, die als Template-Parameter in Frage kommen, kann man das wunderbar in eine DLL packen. Mit oder ohne "in der Klasse". -> explizit instanzieren
Man kann auch die Implementierung ganz normal im Header-File machen, wie bei Templates üblich, und das Template nur für die die am häufigsten verwendeten Typen in der DLL instanzieren (und diese Instanzen dann exportieren).
Zumindest mit MSVC geht das.
Wie es geht kann man sich u.a. in der Standard-Library vom MSVC angucken. std::basic_string<char>, std::basic_string<wchar_t> und einige häufig verwendete Container-Varianten sind z.B. in der Runtime DLL instanziert.