linux-l: C++ (templates, operator overloading)

Guenther Thomsen tho at thomsen.isdn.cs.tu-berlin.de
Mo Aug 2 16:54:18 CEST 1999


In message <19990802114436.A15502 at physik.TU-Berlin.DE>, Samy Khadem-Al-Charieh 
writes:
> Hallo Liste,
> 
> ich hoffe das ist nicht OT, aber ich programmiere ja schließlich unter
> Linux mit egcs und Wipeout (danke für den Tip Michael :-) ).
 naja, es ist nicht wirklich Linux spezifisch und C++ Gurus wuerde ich woanders
suchen aber da ich das auch Wissen sollte, habe ich mich da 'mal reingekniet.

> Folgendes Problem:
> Ich habe eine schöne Klasse genannt monom und weiß nicht, wie ich es machen
> muß, damit ich in der Header-Datei deklarierte Methoden in der .cc-Datei
> definieren kann. Ich schaffe es nur, daß sowohl main.cc als auch monom.cc
> ohne Fehlermeldung kompilieren. Will ich dann linken findet der Linker
> in main dann nicht die Definition in monom.cc.
> Ein weiteres Problem ist, daß ich nicht die Syntax rausfinde, mit der ich
> den <<-Operator überladen kann.
> Damit das ganze etwas klarer wird, hier Auszüge aus meiner Source:
> 
[src]

> Wie gesagt, lasse ich den operator<<-Kram erstmal raus, kompiliert alles,
> aber ich bekomme beim Linken die Fehlermeldung:
> 	"monom.h:8: undefined reference to 'monom<double>::print(void)`"
> Wohlgemerkt ist dies die Zeile des Konstruktors! Nehme ich die m.print();-
> Zeile aus main.cc heraus, geht es wieder!?!?
> 
> Was sagt mir das???

i) ohne die 'm.print();' Zeile in main.cc wird entsprechende Methode nicht
instantiiert und es gibt somit auch keine Fehlermeldung.

ii) Zur Zeit da monom.cc kompiliert wird, ist unbekannt, fuer welche Typen
<t_type> die Methode print() instantiiert werden soll. Da unmoeglich fuer
alle Typen Code erzeugt werden kann, wird gar keiner erzeugt. In `info g++`
wird beschrieben, wie fuer bestimmte, zu erwartende Typen die Codegenerierung
fuer (aeltere?) GNU c++ compiler erzwungen werden kann. Andere Compiler
koennen das vielleicht automatisch (es wird eine 'Repository' erwaehnt) -
wie habe ich mir das vorzustellen?

iii) das Ueberladen von operatoren ist nicht weiter schwierig und wohl
dokumentiert. Richtig knifflig wird es aber im Zusammenhang mit Templates.
Ich habe das nur nach einigem Herumprobieren hinbekommen (Option '-Wall'
erwies sich als hilfreich) - s.u. .

 Hier nun der kompilierbare (egcs-2.91.66 aka egcs release 1.1.2) und
lauffaehige Code: 
--8<-- monom.h
#include <iostream>

template<class t_type>
class monom {
protected:
        int m_order;
        t_type m_coeff;
public:
        inline monom(int o, t_type c) { m_order=o; m_coeff=c; }
        void print();  
        friend ostream& operator<<<t_type>(ostream&, const monom<t_type>&);
};

// operator<< deklarieren (genau so - reine Alchemie)
template<class t_type> 
ostream& operator<<(ostream&, const monom<t_type>&);
-->8--

--8<-- monom.cc
#include "monom.h"
template<class t_type> 
void monom<t_type>::print() {
        cout << m_coeff << "*x^" << m_order << endl;
}


template<class t_type> 
ostream& operator<<(ostream& os, const monom<t_type>& m)
{
	os << m.m_coeff << "*x^" << m.m_order << endl;
	return os;
}


// code Generierung forcieren:
template class monom<double>;
template ostream& operator<<<double>(ostream&, const monom<double>&);
-->8--

--8<-- main.cc
#include "monom.h"
main() {
        monom<double> m(4., 5);
	m.print();
        cout << m;
}
-->8--

> 
> Hilfe !!!!!     ;-)
Keine Panik. Wir sind ja bei Dir ;-)

> 
> Tschüß, Samy.
> 
> PS: Ich lese jetzt schon seit mehreren Tagen im Stroustrup, hat mir aber
> nichts geholfen - zumindest nicht für dieses Problem ;-)
 Ich hab' auch ein wenig in Stroustroup (The C++ Prog. Lang. 2.edit.) und
'C++ Unleashed' geblaettert. Aber das ueberladen von Operatoren mit generischen
Parametern habe ich dort auch nicht gefunden.  Probieren!

Guenther



Mehr Informationen über die Mailingliste linux-l