Problem mit der Implementierung einer Template Klasse



  • Hallo zusammen,
    ich sitze zurzeit an einer Bruchklasse, die Brüche in ein Objekt einlesen soll und diese dann Normaliesieren soll hierbei bekomme ich allerdings einen Fehler bei dem Aufruf des Konstruktors meiner Funktionsklasse mit dem Ich leider nichts anfangen kann : "error: no match for call to '(Bruch<int>) (int, int)' test1(2,4);" ist die Fehler Beschreibung.

    //
    // Created by Sven on 05.06.2019.
    //
    
    #ifndef P8_FRACTION_H
    #define P8_FRACTION_H
    
    #include <iostream>
    
    template<class T> class Bruch {
    private:
        T Zaehler;
        T Nenner;
    
    public:
    void normalisieren(T a, T b);
    T gcd(T a, T b);
    void print(void);
    Bruch(T a, T b);
    ~Bruch();
    
    
    };
    
    
    #endif //P8_FRACTION_H
    
    
    //
    // Created by Sven on 05.06.2019.
    //
    
    #include "Bruch.h"
    #include <iostream>
    using namespace std;
    
    /**
     * Funktion soll den GGt von Zwei Zahlen ermitteln
     * @param Zaehler a und Nenner b
     * @return GGt von a und b
     */
    
    template<class T>
    T Bruch<T>::gcd(T a, T b)
    {
        T rest_aus_ab;
    
        if(b == 0)
        {
            throw "Eine Division durch 0 ist nicht moeglich!";
        }
    
        if(a == 0 || b == 0)
        {
            throw "Der Bruch 0/0 ist 0";
        }
        while(b!=0)
        {
            rest_aus_ab = a % b;
            a = b;
            b = rest_aus_ab;
    
        }
    
        return a;
    
    }
    /**
     * Funktion soll die GGt Funktion aufrufen und danach den Zähler und Nenner Kürzen
     * aehler a und Nenner b
     * Kein Return
     */
    template<class T>
    void Bruch<T>::normalisieren(T a, T b)
    {
        T GGT;
        try {
            GGT = gcd(a,b);
        }
        catch (exception &ex) {
            cerr << ex.what();
        }
    
        Zaehler = Zaehler / GGT;
        Nenner = Nenner / GGT;
    
    }
    
    /**
     *
     * Konstruktor zum Speichern im Objekt und Normalisieren
     * Parameter ein Zaehler a und Nenner b
     */
    
    template<class T>
    Bruch<T>::Bruch(T a, T b)
    {
    
        if(Nenner <0 || Zaehler <0) // Negativ durch Negtaiv ergibt Positiv
        {
            Nenner = Nenner*-1;
            Zaehler = Zaehler * -1;
        }
    
        if(Nenner < 0) //Wechsel des Vorzeichen in den Zähler
        {
            Nenner = Nenner*-1;
            Zaehler = Zaehler * -1;
        }
    
        Zaehler = a;
        Nenner = b;
        normalisieren(a,b);
        //
    }
    
    /**
     * PrintFunktion
     * @Kein parameter
     * Kein return
     */
    
    template<class T>
    void Bruch<T>::print()
    {
        cout << "Der Normalisiert Bruch lautet" << Zaehler <<"/" << Nenner << endl;
    }
    template<class T>
    Bruch<T>::~Bruch()
    {
    
    }
    
    #include <iostream>
    #include "Bruch.h"
    #include "test.h"
    
    using namespace std;
    
    
    int main() {
        Bruch<int> test1(2,4); // Hier entsteht der fehler
        //test1(2,4);
        test1.print();
        return 0;
    }
    

    Kann mir da irgend jemand weiterhelfen ? Ich bin für jede Hilfe Dankbar.
    Mit freundlichen Grüßen
    Sven



  • @SirRust sitze grade nur am Smartphone, daher nur kurz: Implementier deine templated Sachen direkt im Header.



  • Was ist test.h?



  • @SirRust sagte in Problem mit der Implementierung einer Template Klasse:

    Bruch<int> test1(2,4); // Hier entsteht der fehler

    Moin,

    Wenn ich das richtig sehe, fehlt dir das include für deine Implementation des templates.
    Also entweder die Implementation auch in das Header-File mitreinschreiben oder am
    Ende des Headers deine Implementation includen.

    Inhaltlich solltest du in deinem Konstruktor erst deine Member besetzten bevor du mit ihnen arbeitest,
    dein Vorzeichenwechsel ist so grad wenig sinnvoll



  • @manni66
    Das ist eine Testklasse um da einfach mal ein paar werte rein zu schmeißen
    die kann erstmal ignoriert werden



  • @deviloper Die fehlende Implementierung macht sich aber für gewöhnlich erst beim Linken bemerkbar. Er hat aber eine Compilerfehlermeldung erhalten. Trotzdem sollte das Problem auf jeden Fall behoben werden. Vielleicht gibt ja der Compiler nur eine blöde Fehlermeldung aus, denn die fehlende Implementierung ist auch das einzige, was ich so im Moment entdecke. Die Klasse scheint der Compiler ja zu kennen, denn sonst hätte er eine andere Fehlermeldung geschrieben.



  • @SirRust sagte in Problem mit der Implementierung einer Template Klasse:

    @manni66
    die kann erstmal ignoriert werden

    Der gezeigte Code verursacht nicht die Fehlermeldung. Aber ist ja dein Problem...



  • @mgaeckler Evtl. ist die test.h doch spannend. Ggf wird durch den Code darin der Linker-Fehler behoben den wir hier vermissen.



  • @manni66 In der test.h stand nichts drinne ausser einer Klassen definition ohne attriubt oder Methoden deklaration.

    @Alle Ich konnte Das Problem aber soweit lösen. Anscheinend mag der Compiler bei Template Funktionen den Header nicht sondern will direkt die Zuständige .cpp inkludiert haben wenn die Funktion des Headers ausgelagert sind. Jetzt funktioniert es aufjedenfall.



  • @SirRust sagte in Problem mit der Implementierung einer Template Klasse:

    @manni66 In der test.h stand nichts drinne ausser einer Klassen definition ohne attriubt oder Methoden deklaration.

    @Alle Ich konnte Das Problem aber soweit lösen. Anscheinend mag der Compiler bei Template Funktionen den Header nicht sondern will direkt die Zuständige .cpp inkludiert haben wenn die Funktion des Headers ausgelagert sind. Jetzt funktioniert es aufjedenfall.

    Hi,

    das war klar, Templatedefinitionen müssen im Header, da sonst der Compiler die Templateinstanz nicht erstellen kann. Nach meiner Erfahrung erhält man dann aber einen Linkerfehler, wenn man/frau das nicht macht. Bist Du Dir sicher, daß Du die richtige Fehlermeldung zitiert hast?



  • @mgaeckler sagte in Problem mit der Implementierung einer Template Klasse:

    Bist Du Dir sicher, daß Du die richtige Fehlermeldung zitiert hast?

    Es ist nicht die richtige. Die Meldung stammt von //test1(2,4); wenn es nicht auskommentiert ist.



  • @manni66 sagte in Problem mit der Implementierung einer Template Klasse:

    Es ist nicht die richtige.

    Immerhin wurde irgendeine Fehlermeldung angegeben. Das die mit dem gezeigten nichts zu tun hat, ist halt unsere Aufgabe das herauszufinden.

    @SirRust sagte in Problem mit der Implementierung einer Template Klasse:

    if(Nenner <0 || Zaehler <0) // Negativ durch Negtaiv ergibt Positiv

    Ja, aber negativ durch positiv oder positiv durch negativ nicht.



  • Och, wenn wir schon bei solchen Problemen sind, dann finde ich auch

        if(a == 0 || b == 0)
        {
            throw "Der Bruch 0/0 ist 0";
        }
    

    eine schöne Blüte. Erstmal ist 0/0 undefiniert und nicht 0. Zweitens wurde zuvor schon bei if(b == 0) geworfen - man hat hier also niemals 0/0 - und 0/n ist durchaus ein gültiger Bruch für n > 0.

    Und dann frage ich mich noch,

    • warum gcd eine Member-Funktion ist
    • warum normalisieren zwei Parameter hat
    • und welche Brüche denn beim normalisieren Fehler werfen sollten (nicht: welche es hier tun)

  • Mod

    Außerdem viel offensichtlicher: throw von char-Arrays ist … nicht so gut. Besser als std::string (was aktiv gefährlich wäre, da std::string selber etwas werfen könnte), aber trotzdem nutzlos. Denn: Wie fängt man das? catch "Der Bruch 0/0 ist 0" ginge schließlich nicht. catch (const char * exception) ginge zwar, aber was macht man damit? Einen riesigen Fallunterscheidungsblock? Damit hatte man ja das Exceptionhandling ad absurdum geführt.



  • @wob sagte in Problem mit der Implementierung einer Template Klasse:

    "Der Bruch 0/0 ist 0"

    Haha. Wer hat das erfunden? Die Schweitzer?

    gratistip


Anmelden zum Antworten