• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] C++: Problem mit statischer template-funktion

Hallo allerseits,

ich bin relativ neu im objekt-orientierten Programmieren, und hab jetzt ein Problem:
ich hab mir ein paar mathematische Hilfsdateien in einer Klasse zusammengefasst, z.B.:

Code:
//Math.h
class math
{
static double foo1(double x);
static double foo2(double y);
template<typename T> static void foo3(vector<T> v);
};

//Math.cpp
double Math::foo1(double x)
{
.......
}

double Math::foo2(double x)
{
.......
}

template<typename T>
void Math::foo3(vector<T> v)
{
.......
}

//Main.cpp
#include"Math.h"
int main()
{
vector<double> v;
Math::foo3(v);
}

Ein paar Fragen:

1. Macht man das mit "static" so ? Ich finde es sieht schöner aus "Math::foo3(v)" aufzurufen als erst ein Objekt zu erstellen und dann den Zugriffsoperator zu benutzen. Hat das irgendwelche Vor-/Nachteile ?

2. Leider gibt es bei dem Aufbau eine "undefined reference" auf foo3. Wie kann man das richtig machen ? (Ich hab schon viel im Netz gesucht, aber leider nichts gefunden...)

Danke im Voraus,
Gruß David
 
zu 1)
Was soll eine Klasse ohne ein einziges Attribut darstellen? Ich bin zwar nicht ein Profiprogrammierer würde aber sagen, die Bedeutung von objektorientiert ist nicht richtig angekommen. Meiner Meinung nach sind hier einfache Funktionen in einen eigenen Namensraum die bessere Lösung.

Beispiel:
Code:
#include <cmath>

namespace MyMath
{
    /**
     * \brief round für den Datentyp double.
     */
    using ::round;

    /**
     * \brief Überladen von round für float.
     */
    inline float
    round(float __x)
    { return roundf(__x); }

    /**
     * \brief Überladen von round für long double.
     */
    inline long double
    round(long double __x)
    { return roundl(__x); }
}


zu 2)
Das richtige Stichwort lautet, Instanzbildung bzw. Instanzdeklaration von Templates.
Bei solchen Fragen hilft nur ein vernünftigen Buch, oft wird nicht mal darauf hingewiesen das die Instanzbildung von Templates zu Problemen führen kann.
Code:
template<typename T>
void Math::foo3(vector<T> v)
{
.......
}

// Explizite Instanzdeklaration
template
void Math::foo3(vector<double> v);
 
zu 1)
Ja, es ist durchaus sinnvoll statische Funktionen in einer eigenen Klasse zu Kapseln. Man könnte zwar auch ein namespace mit Klassenlosen Funktionen daraus machen, aber so ist es mindestens genauso sauber.
Entgegen der Meinung meines Vorredner muss nicht jede Klasse einem Objekt in der Wirklichkeit entsprechen. Klassen sind unter anderem dafür da eine sinnvolle Trennung von Funktionalität zu liefern.

zu 2) und zu Template-Funktionen:
Template Funktionen haben eine etwas eigene Syntax. Da hilft in der Tat ein gutes Buch am besten weiter.
Ansonsten habe ich noch im Kopf, dass man Template-Funktionen innerhalb des Headers implementieren muss. Laut C++ Standard sollte es zwar mit dem "export" Schlüsselwort auch möglich sein die Template-Funktion woanders zu definieren, aber diese Vorgehensweise unterstützt weder GCC, noch MSVC++.
Wenn du zu große Probleme mit Template-Funktionen hast, kannst du auch ebensogut überladene Funktionen verwenden. Das macht nur mehr Schreibarbeit und ist weniger elegant, ist aber genauso performant. (Der Compiler mach intern eigentlich auch nichts anderes)

Haegar
 
Danke für eure Antworten.
Ich versuchs nochmal mit Namespaces.

Kann jemand vielleicht noch genauer erklären wie man dennoch die Template Funktionen statisch deklariert. Ich bekomm immer ne "undefined reference"...

Gruß, David
 
http://www.mathematik.uni-marburg.de/~cpp/templates/index.html
http://www.cplusplus.com/doc/tutorial/templates.html
http://informatik.unibas.ch/lehre/ss05/cs104/lectures/08_C++.pdf
http://www4.informatik.uni-erlangen.de/Lehre/SS07/V_OSE/Skript/11-Templates-2x2.pdf
 
zu 1)
Da die Klasse nichts weiter macht als über den Klassennamen einen Namensraum zu generieren, halte ich es für sinnvolle die Funktionen direkt in einen Namensraum zu setzen. Das Hauptziel einer Klasse liegt meiner Meinung darin, den Zugriff auf Attribute (Datenelemnete) auf bestimmte Funktionen (Methoden) zu beschränken. Und wo keine Datenelemente sind, da gibt es eigentlich nichts zu kapseln. Aber sicher kann man da verschiedener Meinung sein.

zu 2)
davidhigh schrieb:
Kann jemand vielleicht noch genauer erklären wie man dennoch die Template Funktionen statisch deklariert. Ich bekomm immer ne "undefined reference"...
Ja, explizite Instanzdeklaration. Diese muss (irgendwo) hinter der Definition des Funktionstemplates (hier Math.cpp) erfolgen. Habe ich aber in meinen voerherigen Beispiel zu 2) gezeigt. Die letzten drei Codezeilen sehen da so aus:
Code:
// Explizite Instanzdeklaration
template
void Math::foo3(vector<double> v);
 
Oben