undefined reference

Dieses Thema im Forum "C/C++" wurde erstellt von dr.krabbe, 04.08.2005.

  1. #1 dr.krabbe, 04.08.2005
    dr.krabbe

    dr.krabbe Jungspund

    Dabei seit:
    09.06.2005
    Beiträge:
    21
    Zustimmungen:
    0
    Hallo! Ich bin neu im c++-programmieren und lerne (immer noch) nach einem Buch. Ich habe eine Datei, mit einer main und eine .gcc und .h gleichen Namens. Und es geht irgendwie nicht.
    So sieht die test_queue.cpp aus:

    #include <iostream>
    #include "tqueue.h"

    using namespace std;

    int main(void)
    {
    cout << "START!!"<<endl;
    TQueue<int> tq1(9);

    return(0);
    }



    so die tqueue.h:

    #ifndef __TQUEUE_H
    #define __TQUEUE_H

    template<class Typ>
    class TQueue
    {
    public:
    explicit TQueue(unsigned long);
    ~TQueue(void);
    bool Enqueue(Typ);
    Typ Dequeue(void);
    bool isEmpty(void);

    private:
    Typ *data;
    unsigned long anz;
    unsigned long maxanz;
    unsigned long inpos, outpos;
    };
    #endif __TQUEUE_H


    und so die tqueue.cpp:

    #include "tqueue.h"

    template<class Typ>
    TQueue<Typ>::TQueue(unsigned long s)
    {
    data = new(Typ);
    if(data)
    {
    anz=inpos=outpos=0;
    maxanz = s;
    }
    else
    {
    anz=inpos=outpos=0;
    }
    }

    template<class Typ>
    TQueue<Typ>::~TQueue(void)
    {
    if(data)
    delete[](data);
    }

    template<class Typ>
    bool TQueue<Typ>::Enqueue(Typ w)
    {
    if(anz<maxanz)
    {
    anz++;
    data[inpos++]=w;
    if(inpos == maxanz)
    inpos = 0;
    return(true);
    }
    else
    {
    return(false);
    }
    }

    template<class Typ>
    Typ TQueue<Typ>::Dequeue(void)
    {
    if(anz > 0)
    {
    unsigned long aktpos = outpos;
    if((++outpos) == maxanz)
    outpos=0;
    anz--;
    return(data[aktpos]);
    }
    else
    {
    return(0);
    }
    }

    template<class Typ>
    bool TQueue<Typ>::isEmpty(void)
    {
    return(anz == 0);
    }



    und so ist beim aufruf von g++ die Fehlermeldung:


    g++ test_queue.cpp
    In Datei, eingefügt von test_queue.cpp:2:
    tqueue.h:20:8: Warnung: mehrere Token am Ende der Direktive #endif
    /tmp/cct0FJqL.o(.text+0x43): In function `main':
    : undefined reference to `TQueue<int>::TQueue[in-charge](unsigned long)'
    /tmp/cct0FJqL.o(.text+0x4e): In function `main':
    : undefined reference to `TQueue<int>::~TQueue [in-charge]()'
    collect2: ld returned 1 exit status



    Wäre toll, wenn ihr mir sagt, woran das liegt.
    Danke schon mal...
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 dr.krabbe, 04.08.2005
    dr.krabbe

    dr.krabbe Jungspund

    Dabei seit:
    09.06.2005
    Beiträge:
    21
    Zustimmungen:
    0
    Das Smiley hat der selbst gemacht.
    : D => :D
     
  4. #3 MrFenix, 04.08.2005
    Zuletzt bearbeitet: 04.08.2005
    MrFenix

    MrFenix Executor

    Dabei seit:
    16.10.2004
    Beiträge:
    480
    Zustimmungen:
    0
    Ort:
    Siegen, NRW
    Probiers mal mit
    Code:
    # gcc -c tqueue.cpp
    # gcc -o test test_queue.cpp tqueue.o
    
    Das erstellt erst den Assembler Code für tqueue.cpp. Dannach wird der für test_tqueue.cpp erstellt, der von tqueue wird diesem zu Verfügung gestellt und das Ergebnis wird gelinkt.
    -c ist dafür, dass nur der Assemblercode erstellt wird und nicht gelinkt wird.
    -o bennennt die fertige Executable in "test".

    Eine kostenlose und sehr gute Anleitung für den Umgang mit gcc findet man auch unter http://www.oreilly.de/german/freebooks/linux_install/kap061.html .

    Btw.: Es ist besser, wenn du hier die code tags beim Source posten benutzt
     
  5. #4 dr.krabbe, 05.08.2005
    dr.krabbe

    dr.krabbe Jungspund

    Dabei seit:
    09.06.2005
    Beiträge:
    21
    Zustimmungen:
    0
    OK. Ich habe diese beiden befehle ausgeführt. Fehlermeldung ist für mich noch unverständlicher geworden:

    Code:
    gcc -c tqueue.cpp
    
    In Datei, eingefügt von tqueue.cpp:1:
    tqueue.h:20:8: Warnung: mehrere Token am Ende der Direktive #endif
    
    gcc -o test test_queue.cpp tqueue.o
    
    In Datei, eingefügt von test_queue.cpp:2:
    tqueue.h:20:8: Warnung: mehrere Token am Ende der Direktive #endif
    /tmp/cczJsN0W.o(.text+0x1b): In function `main':
    : undefined reference to `std::cout'
    /tmp/cczJsN0W.o(.text+0x20): In function `main':
    : undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
    /tmp/cczJsN0W.o(.text+0x28): In function `main':
    : undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
    /tmp/cczJsN0W.o(.text+0x30): In function `main':
    : undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
    /tmp/cczJsN0W.o(.text+0x43): In function `main':
    : undefined reference to `TQueue<int>::TQueue[in-charge](unsigned long)'
    /tmp/cczJsN0W.o(.text+0x4e): In function `main':
    : undefined reference to `TQueue<int>::~TQueue [in-charge]()'
    /tmp/cczJsN0W.o(.text+0x77): In function `__static_initialization_and_destruction_0(int, int)':
    : undefined reference to `std::ios_base::Init::Init[in-charge]()'
    /tmp/cczJsN0W.o(.text+0xa8): In function `__tcf_0':
    : undefined reference to `std::ios_base::Init::~Init [in-charge]()'
    /tmp/cczJsN0W.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
    collect2: ld returned 1 exit status

    was ist das jetzt?
     
  6. Andrea

    Andrea Routinier

    Dabei seit:
    01.12.2003
    Beiträge:
    418
    Zustimmungen:
    0
    Ort:
    Bielefeld
    Hallo,

    ich hab auch nicht soooo viel Ahnung, aber ich glaube die ganzen letzten Fehlermeldungen kommen daher, dass du ein c++ Programm mit dem C Kompiler (gcc) kompilierst bzw. kompilieren willst =). Tausch mal das gcc gegen g++ aus.

    Andrea
     
  7. #6 MrFenix, 05.08.2005
    Zuletzt bearbeitet: 05.08.2005
    MrFenix

    MrFenix Executor

    Dabei seit:
    16.10.2004
    Beiträge:
    480
    Zustimmungen:
    0
    Ort:
    Siegen, NRW
    Ich hab grade mal ne Weile gebastelt und einige Verbesserungsvorschläge:
    1. Mit g++ compilieren (wie konnte ich das vergessen?)
    2. An das Ende von tqueue.cpp schreiben:
    Code:
    template class TQueue<int>
    
    Hier scheint (warum auch immer) explizite Instanziierung notwendig zu sein.
    3. Bei tqueue.h die Zeile
    Code:
     explicit TQueue(unsigned long);
    
    durch
    Code:
     TQueue(unsigned long s);
    
    ersetzen, weil es einfach besser aussieht (finde ich).
    4. Bei tqueue.h am Ende
    Code:
    #endif __TQUEUE_H
    
    durch
    Code:
    #endif //__TQUEUE_H
    
    ersetzen, damit die Warnmeldung weggeht.
    Oh und du kannst übrigens auch mit
    Code:
    # g++ -o test test_queue.cpp tqueue.cpp
    
    compilieren, das passt in eine Zeile :) .

    Btw.: Irgendwie hab ich bei c++ noch nie Templates gebraucht. Ich weiß zwar, dass es sowas gibt, aber lasse die Finger möglichst davon, weil das so komplex und fehleranfällig ist.
     
  8. oenone

    oenone Freier Programmierer[Mod]

    Dabei seit:
    22.08.2002
    Beiträge:
    599
    Zustimmungen:
    0
    Ort:
    Mannheim
    gcc ist für C, g++ ist für C++, gcj ist für Java, g77 ist für Fortran, etc...

    C++ und C sind zwei verschiedene Programmiersprachen.

    auf bald
    oenone
     
  9. Konrad

    Konrad Jungspund

    Dabei seit:
    13.06.2004
    Beiträge:
    20
    Zustimmungen:
    0
    Hallo,
    dein/das Problem ist das der gcc das "export" Keyword von C++ nicht kennt und dadurch die Deklaration und Definition der Template-Klasse in einer Datei sein müssen.
    Das heißt alles aus tqueue.cpp in tqueue.h packen.

    Alternativ kannst du aber auch einfach ein ' #include "tqueue.cpp" ' vor dem #endif in die tqueue.h schreiben. Dann darfst/brauchst du die tqueue.cpp aber nicht mehr extra compilen/mitlinken.
    g++ test_queue.cpp -o test_queue
    würde dann reichen.
     
  10. #9 dr.krabbe, 10.08.2005
    dr.krabbe

    dr.krabbe Jungspund

    Dabei seit:
    09.06.2005
    Beiträge:
    21
    Zustimmungen:
    0
    Konrad hatte Recht!!!!
    Ich weiß zwar nicht warum und was es eigentlich bedeutet, aber durch ein zusätzliches include der .cpp-datei hats geklappt.

    Ich habe vorher natürlich schon g++ benutzt, das war wohl nur ein Fehler meinerseits.sorry.

    Aber was soll ich jetzt tun, damit mein g++ export versteht? Ist doch nicht normal, oder?


    Danke für die vielen Lösungen!!
     
  11. Konrad

    Konrad Jungspund

    Dabei seit:
    13.06.2004
    Beiträge:
    20
    Zustimmungen:
    0
    Es gibt eigentlich keine Möglichkeit dem gcc "export" beizubringen.
    Das ist einfach ein C++ Keyword welches es ermöglichen soll das bei Templates dieselbe Aufteilung von Schnittstelle (.h) und Definition (.cpp) wie bei "normalen" Klassen möglich ist.
    Bisher kenn Ich nur einen Compiler der das kann und zwar Comeau.

    Unter normaler Aufteilung verstehe Ich das hier:
    Code:
    //main.cpp:
    
    #include "klasse.h"
    
    int main() { /* Klasse benutzen ... */ }
    
    //klasse.h
    /*
     * Klassen-Schnittstelle
     * /
    
    //klasse.cpp
    #include "klasse.h"
    /*
     * Implementierung der Klasse
     */
    
    In dem Fall kann Ich "Klasse" in meiner main() verwenden, die Aufrufe werden beim kompilieren mit Platzhaltern versehen und später, beim Linken, mit dem richtigen "Inhalt" aus klasse.cpp ersetzt.

    Das Problem bei den Templates ist das sie zur Compile-Zeit "ausgeführt" werden und zu der Zeit verständlicherweise dann auch die vollständige Implementierung der Klassen/Funktionen vorhanden sein müssen.
    Da die C++ Compiler aber jede .cpp Datei separat compilen und das Programm erst anschließend vom Linker "zusammengebaut" wird, würde der Compiler die Template-Definitionen beim Compile-Vorgang nicht kennen. (Da sie ja in einer separaten .cpp Datei ist)

    "export" sollte einen ähnlichen Effekt wie bei "normalen" Klassen zur Folge haben. Es ist nur ein wenig schwieriger da der Compiler bei main.cpp das Template nicht mit seinen Parametern bearbeiten kann (Da Implementierung unbekannt...) und die klasse.cpp das Problem mitsich bringt das der Compiler nicht weiß für welche Parameter das Template instanziiert werden soll.

    So long..
    hoffe du hast's verstanden :)
     
  12. #11 MrFenix, 14.08.2005
    MrFenix

    MrFenix Executor

    Dabei seit:
    16.10.2004
    Beiträge:
    480
    Zustimmungen:
    0
    Ort:
    Siegen, NRW
    Sry, aber mal ehrlich: Sowas vermeidet man doch, wenns irgendwie geht beim Programmieren. Wenn ich das was ich durch das Template an Zeit / Aufwand etc. einspare wieder für solche Überlegungen draufgehen lassen muss, brauch ich auch kein Template mehr.
    Das soll jetzt nicht gegen Templates im Allgemeinen sein, aber das hier ist schon ein arg krummer Fall (der auch nicht so oft vorkommt denke ich)...
     
  13. Konrad

    Konrad Jungspund

    Dabei seit:
    13.06.2004
    Beiträge:
    20
    Zustimmungen:
    0
    Was meinst du genau?

    Solche Überlegungen sind ja gar nicht nötig/wichtig. Der Header der Template-Klasse muss einfach auch die Implementierung beinhalten. Mehr nicht.

    Naja, was heißt krummer Fall.. Der Compiler braucht halt das komplette Template zur Übersetzungszeit, "export" ist zwar im Standard vorgesehen wird aber bisher nur von Comeau angeboten.
    Und "krumm" ist es auch nicht. ;) Das Problem ist grundsätzlich vorhanden wenn es um Templates geht.
     
  14. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  15. #13 MrFenix, 14.08.2005
    MrFenix

    MrFenix Executor

    Dabei seit:
    16.10.2004
    Beiträge:
    480
    Zustimmungen:
    0
    Ort:
    Siegen, NRW
    Erstmal: Wo war eigentlich das Problem bei meinem Vorschlag? (das ist jetzt wirklich nicht beleidigt oder provozierend zu verstehen, es interessiert mich nur wirklich, warum man das export noch zusätzlich braucht)
    Und vermeiden würde ich persönlich alles, was mich zu sehr auf einen Compiler einschränkt. Es beißt sich etwas mit meinen Vorstellungen Dinge möglichst einfach zu halten...

    Btw.: Ich befürchte, dass das hier noch in einen Glaubenskrieg ausartet.. Das ist aber wirklich nicht meine Absicht, denn es wäre leicht lächerlich sich über Klassentemplates zu streiten ^^
     
  16. Konrad

    Konrad Jungspund

    Dabei seit:
    13.06.2004
    Beiträge:
    20
    Zustimmungen:
    0
    Naja, Ich möchte nicht erst alles mit -c in Assembler Code umwandeln und anschließend mit -o die executable bauen. Jetzt, auf der Console ist das nicht sooo das Problem. Aber stell dir mal vor Ich benutze Visual Studio (blöde Idee ;)), dann könnte Ich ja auch nicht mehr einfach "Build" benutzen sonder müsste da noch in den makefiles rumschreiben damit erst der Assemblercode erstellt wird.
    Bei größeren Projekten wird sowas auch schnell unübersichtlich.

    Zu deinem 2ten Post, sehe Ich gerade erst:
    Du instanziierst ja TQueue<Int> schon in der tqueue.cpp. Was wäre aber wenn er in main.cpp auf einmal TQueue<std::string> oder was weiß Ich braucht? Soll er dann immer in TQueue.cpp das template instanziieren?
    Ist (imo) irgendwie nicht so toll und widerspricht auch ein bisschen dem Prinzip der Wiederverwendbarkeit und auch dem Sinn der Templates.
    Ich kann ja erstmal nur TQueue<int> benutzen und dann bräuchte Ich die Templates gar nicht sonder könnte gleich die Klasse "normal" mit int programmieren und würde mir das hier alles sparen.

    Sehe Ich genauso. Ich wollte auch niemandem dazu raten "export" zuverwenden, da es wie gesagt zwar im Standard ist aber nicht umgesetzt wird (leider).

    Ich finde es nicht komplizierter als deine Variante mit dem Assembler-Code (soll kein Angriff sein).
    Ist doch wirklich nicht schwer in "klasse.h" noch einmal "klasse_impl.h"
    zu includen um die Implementationen parat zuhaben, oder?

    Ist/war auch nicht meine Absicht. Ich wollte nur dr.krabbe das Problem, was ja eigentlich keins ist, mit den Templates erklären:

     
Thema:

undefined reference

Die Seite wird geladen...

undefined reference - Ähnliche Themen

  1. Noch ein 'undefined reference to'-Problem

    Noch ein 'undefined reference to'-Problem: Servus alle Seit langem versuche ich, dsniff 2.3 auf meinem Suse 10.1 (gcc 4.1.0) Rechner zu compilieren+installieren. Nach einigen Hürden habe...
  2. undefined reference beheben

    undefined reference beheben: Hi, ich will das Programm dab.c compilieren (Quelle: http://www.2600.org/code/221/dab.c) bekomme aber folgende Fehlermeldung beim ausführen von...
  3. 'libraryname': undefined reference to 'functionname'

    'libraryname': undefined reference to 'functionname': Hallo zusammen, Erst mal das Allgemeine: Ich benutze SuSE 10.3 als Betriebssystem und Eclipse als IDE. Meine C++ Kenntnisse sind nicht wirklich...
  4. undefined reference

    undefined reference: Hallo alle zusammen, Ich hab da so ein nerviges Problem mit der Installation von Rythmbox Music Player. Da ich noch Dapper Drake habe wollte ich...
  5. gtk+extra undefined reference

    gtk+extra undefined reference: Ich hab ein problem mit gtk+extra ich will einfach nur ein testprogramm zum laufen bringen, nix besonderes ich will nur mal was zum laufen...