Linker: Einbinden einer Headerdatei in alle Klassen



  • Halllo,

    ich lege gerade eine neues Projekt an, das neben Klassen auch eine Headerdatei namens "allgemein.h" enthalten soll, damit ich dort klassenunabhängige Konvertierungsfunktionen etc. unterbringen kann.

    Die sieht im Moment etwa so aus:

    #pragma once
    #ifndef _allgemein_h
    #define _allgemein_h
    
    #pragma warning( disable : 4705 )
    
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <iomanip>
    #include <string>
    #include <stdlib.h>
    #include <math.h>
    #include <vector>
    #include <map>
    #include <set>
    #include <list>
    #include <fstream>
    #include <sstream>
    #include <iostream>
    
    using namespace std;
    
    ofstream logfile;
    
    template<class T> string tos(const T& aval, const int & abreite=0)
    {
      //...
    }
    
    //weitere Funktionen
    #endif
    

    Wenn ich diesen Header nun in der main und einer Klasse (in der cpp-Datei) einbinde, meckert der Linker, dass Objekte mehrfach definiert sind. Ich dachte, dieses Problem ließe sich mit Compilerdirektiven umgehen?

    Also im Prinzip geht es um das generelle Problem, globale Funktionen oder Variablen für alle Klassen zugänglich zu machen.

    Vielen Dank.



  • #pragma once 
    
    #ifndef _allgemein_h 
    #define _allgemein_h
    

    Irgendwie doppel gemoppelt....

    ofstream logfile;
    

    Was meinst du wie oft diese Variable in deinem Projekt existiert, wenn du diese Zeile in jedem deiner Cpp-Dateien stehen hast?



  • C/C++ Code:
    #pragma once

    #ifndef _allgemein_h
    #define _allgemein_h

    Irgendwie doppel gemoppelt....

    Äh, OK, pardon, das pragma fügt das Visual Studio selbst ein. Ich bin eher die andere Variante gewohnt...

    C/C++ Code:
    ofstream logfile;

    Was meinst du wie oft diese Variable in deinem Projekt existiert, wenn du diese Zeile in jedem deiner Cpp-Dateien stehen hast?

    Ja schon gut, aber irgendwie komm ich nicht dahinter, wie ich z.B. Konstanten oder eben ein Logfilestream so definiere, dass es überall zugänglich ist. Nehmen wir an, ich brauche die Konstante PI. Wohin schreibe ich mein

    const double PI = 3.141
    

    ???



  • Da wir uns in C++ befinden würde ich Klassenvariablen verwenden:

    h:

    class Math
    {
        const static double sm_Pi;
    };
    

    cpp:

    double Math::sm_Pi = 3.14;
    

    Dann schweben die Variablen nicht so frei im Raum... und dein Logstream gehört doch zu einer Log-Klasse/Schnittstelle oder? 😃



  • Hallo,
    Konstanten kannst du problemlos in Headern definieren. Variablen wie logfile dürfen hier allerdings nur deklariert, nicht aber definiert werden. Die einzige Definition kommt dann in eine cpp-Datei.

    // allgemein.h
    #include <fstream>
    
    extern ofstream logfile; // Deklaration
    
    // allgemein.cpp
    #include "allgemein.h"
    
    ofstream logfile;       // Definition
    


  • Solange die Konstanten von einem elementaren Typ sind. Ansonsten könnte es auch schon mal schiefgehen (z.B. in VC++ 6 innerhalb von Klassen).



  • Ja, mit extern klappt´s.

    Was allerdings nicht klappt, sind Templatefunktionen. Da bekomme ich nichtaufgelöste externe Verweise.

    also:

    main.cpp

    #include "allgemein.h"
    
    int main(int argc, char* argv[])
    {
    tausche(a,b);
    return 0;
    }
    

    allgemein.h

    #ifndef _allgemein_h
    #def _allgemein_h
    template<class T> void tausche( T &left, T &right);
    #endif
    

    allgemein.cpp

    template<class T> void tausche( T &left, T &right)
    {
        T temp;
        temp = left;
        left = right;
        right = temp;
    }
    

    Mit anderen Funktionen geht es!
    War das nicht irgendwie immer so, dass man auch bei Templateklassen nur die Headerdatei hat und keine cpp 😕



  • KeineAhnung78 schrieb:

    Mit anderen Funktionen geht es!
    War das nicht irgendwie immer so, dass man auch bei Templateklassen nur die Headerdatei hat und keine cpp 😕

    Wieso "AUCH" bei Templateklassen? Gerade bei Templateklassen, ja!

    Der Grund ist dass es eben ein Template ist. Also eine Vorlage, aus der erst bei Benutzung (oder expliziter Instanziierung) Code wird. Woher soll der Compiler beim Compilieren von (z.B.) a.cpp wissen wie das Template definiert ist wenn es statt im Header in (z.B.) b.cpp steht? 🙂



  • Du kannst keine Templates exportieren. Du kannst ausgeprägte Templates exportieren (mußt sie also bereits in der Dll irgendwo verwendet haben) oder aber du prägst die Templates einfach in jeder Bibliothek in der du sie brauchst neu aus.



  • OK, hab´s kapiert. Mal sehen, wo das nächste Problem auftaucht... 😃


Anmelden zum Antworten