Auf Klasse in anderer cpp-Datei zugreifen



  • Hallo Leute,

    ich bin neu in C++ und will mich hineinarbeiten. Zum Start möchte ich ein Konsolenprogramm bauen, der mir eingaben in eine Textdatei speichert.

    Da ich aus Java komme...

    Ich habe 2 cpp-Dateien:

    start.cpp

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    void main(){
    	string vorname;
    	string tel;
    
    	cout << "Vorname:" << endl;
    	cin >> vorname;
    	cout << "Telefonnummer:" << endl;
    	cin >> tel;
    }
    

    Eintrag.cpp

    #include <string>
    
    using namespace std;
    
    	class Eintrag{
    		public:
    			Eintrag();
    			~Eintrag();
    		private:
    			int id;
    			string vorname;
    			string nachname;
    			string tel;
    	};
    
    	Eintrag::Eintrag(){
    	}
    
    	Eintrag::~Eintrag(){
    	}
    

    Das Problem ist, dass ich nicht weiss, wie ich auf die Klasse Eintrag von start.cpp aus zugreifen kann. In Java die IDE die Klasse sofort, falls in einem anderen package, nach dem import. wie ist es denn in c++..

    Danke im voraus.



  • start.cpp

    #include <iostream>
    #include <string>
    
    #include "Eintrag.h"
    
    using namespace std;
    
    void main()
    {
        string vorname;
        string tel;
    
        cout << "Vorname:" << endl;
        cin >> vorname;
        cout << "Telefonnummer:" << endl;
        cin >> tel;
    
        Eintrag eintrag( // passender c-tor fehlt.
    }
    

    Eintrag.h

    #ifndef EINTRAG_H_INCLUDED
    #define EINTRAG_H_INCLUDED EINTRAG_H_INCLUDED
    
    #include <string>
    
    class Eintrag
    {
        public:
            Eintrag();
            ~Eintrag();
        private:
            int id;
            std::string vorname;
            std::string nachname;
            std::string tel;
    };
    
    #endif /* EINTRAG_H_INCLUDED */
    

    Eintrag.cpp

    #include "Eintrag.h"
    
    Eintrag::Eintrag()
    {
    }
    
    Eintrag::~Eintrag()
    {
    }
    


  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++ (auch C++0x und C++11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hallo Swordfish,

    wow, das scheint mir etwas umständlich... Ist das die gängige Praxis?



  • @Swordfish: soll dein Beitrag eine Korrektur sein?

    Kenan, den default-Konstruktor und -Destruktor brauchst du in der Form nicht hinschreiben (weder Deklaration noch Definition), weil sie implizit erzeugt werden. Den String-Header brauchst du auch nur einmal einfügen, und zwar dort, wo du sie brauchst. Das Objekt erzeugen:

    Eintrag buchung;
    

    Und ja, du sollst für jede Klasse eine separate cpp-Datei erstellen.



  • Hallo Rewind,

    den Kontruktor habe ich hineingeschrieben, weil ich eigentlich die id, den namen und die telefonnummer als parameter später übergeben möchte. Die Getter und Setter Methoden sollen dazu dienen einen Eintrag nachträglich zu ändern.

    Ich verstehe leider deinen Code nicht so ganz:

    Eintrag buchung
    

    Wenn ich den so in meine start.cpp eintrage, kriege ich eine Fehlermeldung, dass "Eintrag nicht definiert ist"...
    Muss ich ihn(Eintrag.cpp) mit irgendeinem import/include Befehl in die start.cpp packen?

    OK, also für jede Klasse eine seperate Klasse(ist wohl bei jeder Programmiersprache so)



  • Sorry, ich hätte das verständlicher schreiben sollen:

    #include <iostream>
    
    #include "Eintrag.h"
    
    int main()    //void main() gab's nur in C
    {
        std::string vorname;
        std::string tel;
    
        std::cout << "Vorname:\n";
        std::cin >> vorname;
        std::cout << "Telefonnummer:\n";
        std::cin >> tel;
    
        Eintrag buchung; //später: Eintrag buchung (/*deine Parameter*/);
        //buchung.machWas();
    }
    

    Eintrag.h

    #ifndef EINTRAG_H
    #define EINTRAG_H
    
    #include <string>
    
    class Eintrag
    {
        public:
            Eintrag();
            ~Eintrag();
        private:
            int id;
            std::string vorname;
            std::string nachname;
            std::string tel;
    };
    
    #endif /* EINTRAG_H_INCLUDED */
    

    Eintrag.cpp

    #include "Eintrag.h"
    
    Eintrag::Eintrag()
    {
    }
    
    Eintrag::~Eintrag()
    {
    }
    


  • Kenan schrieb:

    Hallo Rewind,

    den Kontruktor habe ich hineingeschrieben, weil ich eigentlich die id, den namen und die telefonnummer als parameter später übergeben möchte. Die Getter und Setter Methoden sollen dazu dienen einen Eintrag nachträglich zu ändern.

    Ich verstehe leider deinen Code nicht so ganz:

    Eintrag buchung
    

    Wenn ich den so in meine start.cpp eintrage, kriege ich eine Fehlermeldung, dass "Eintrag nicht definiert ist"...
    Muss ich ihn(Eintrag.cpp) mit irgendeinem import/include Befehl in die start.cpp packen?

    du musst

    #include "Eintrag.h"
    

    einfügen (so in etwa wie ein import bei java)
    Wichtig: die .h, nicht die .cpp! (Dass er dann weiß, was genau er machen soll(was ja in der cpp steht), löst dann der Linker auf)

    Kenan schrieb:

    OK, also für jede Klasse eine seperate Klasse(ist wohl bei jeder Programmiersprache so)

    In c++ musst du das nicht, aber es ist schöner so 😉



  • Ahja, ich muss also eine Header Datei erstellen, namens Eintrag.h.
    Darin könnte ich ja auch alle Funktionen programmieren und könnte so auf Eintrag.cpp verzichten? Oder ist es besser, Eintrag.cpp drinzulassen und die Funktionen darin zu implementieren, die Eintrag.h bietet?



  • Kenan schrieb:

    Oder ist es besser, Eintrag.cpp drinzulassen und die Funktionen darin zu implementieren, die Eintrag.h bietet?

    Ja.

    DerBaer schrieb:

    Kenan schrieb:

    OK, also für jede Klasse eine seperate Klasse(ist wohl bei jeder Programmiersprache so)

    In c++ musst du das nicht, aber es ist schöner so 😉

    Ich habe ehrlich gesagt nicht ganz verstanden, was Kenan damit meint, aber vielleicht kannst du es mir erklären... Wenn er mit "Klasse" die Unterteilung in cpp- und h-Dateien meint, dann hat das nichts mit Schönheit, sondern mit dem praktischen Nutzen zu tun. In einer Datei überschaubarer Größe kann ich viel schneller bestimmte Funktionen oder Stellen finden. Es ist also übersichtlicher. Zum anderen übersetzt der Compiler nur die Dateien, die auch geändert wurden. Bei großen Projekten macht sich der Unterschied bemerkbar.



  • du könntest nur in der Eintrag.h code schreiben, aber das macht man normalerweise nicht. In den Header (.h) gehört nur rein, welche Klassen es gibt und wie die Aufgebaut sind(Funktionen etc.).

    Dadurch kannst du 1. Benutzern deiner Klassen nur die kleinen Header geben und er weiß trotzdem, was die Klasse alles kann und 2. spart man sich viel Zeit beim compilieren. Denn jedesmal wenn du irgendwas mit der Klasse Eintrag machen willst, musst du in der gleichen Datein ein #include "Eintrag.h" machen, sodass immer wenn du die Datei kompilierst, auch die Eintrag.h mit analysiert wird. Ist das nur ne Deklaration geht das rel. schnell, muss der Compiler aber erst deine tausend Zeilen Code parsen, dauert das.



  • [Rewind] schrieb:

    @Swordfish: soll dein Beitrag eine Korrektur sein?

    Jein. Lösung des OPs Problems. void main() hab' ich übersehen.

    [Rewind] schrieb:

    [...] den default-Konstruktor und -Destruktor brauchst du in der Form nicht hinschreiben

    Jo, hätt ich ihm sagen sollen.

    Kenan schrieb:

    [...] Ist das die gängige Praxis?

    Ja. Trennung von Interface und Implementierung - die Implementierung geht den benutzer einen feuchten Kehricht an.

    Kenan schrieb:

    Darin könnte ich ja auch alle Funktionen programmieren und könnte so auf Eintrag.cpp verzichten? Oder ist es besser, Eintrag.cpp drinzulassen und die Funktionen darin zu implementieren, die Eintrag.h bietet?

    Technisch ausschlaggebend ist, ob du die Methoden in der Klasse

    class foo_t{
        public:
            void say_hello() { std::cout << "Hello"; }
    };
    

    oder außerhalb

    class foo_t{
        public:
            void say_hello();
    };
    
    void foo_t::say_hello()
    {
        std::cout << "Hello";
    }
    

    definierst. Deklarfinierst du sie in der Klasse bedeutet das für den Compiler ein implizites inline - verrät dir Google. Definitionen, die nicht in der Klasse erfolgen in eine gleichnamige .cpp zu schreiben ist gängige Praxis.



  • Alles klar, vielen Dank für die Informationen.
    Jetzt ist mir klar, was Headerdateien sind. Cool !
    So, jetzt würde mich folgendes interessieren. In java gibt es
    den Datentype atomicinteger. Dieser Datentype hat die Methode incrementAndget()
    welches automatisch den integer hochzaehlt. Sehr praktisch bei Vergabe von
    IDs für Objekte. Das brauche ja auch ich, denn ich will, dass jeder Eintrag auch
    eine ID bekommt, unter der es dann später beim einlesen der Textdatei gefunden werden kann. Gibt es denn auch so ein Datentyp für C++?



  • also ich bin jetzt auch noch eher am anfang aber ich würde mal behaupten das ganze mit header und cpp dateien zu machen hat enorme vorteile bei der gestaltung von funktionen.

    kurz was aus dem kopf

    // header1.h
    
    void funktion1();
    void funktion2();
    void funktion3();
    
    // header1.cpp
    
    funktion1()
    {
       funktion2(); // das würde ohne die header wahrscheinlich nicht gehen, da der compiler die funktion3 noch nicht kennt, durch die header hat er schonmal von der gehört und weiß wo die funktion in der cpp steht
    }
    
    funktion2()
    {
       // tu was
    }
    


  • auchAnfanger schrieb:

    also ich bin jetzt auch noch eher am anfang aber ich würde mal behaupten das ganze mit header und cpp dateien zu machen hat enorme vorteile bei der gestaltung von funktionen.

    kurz was aus dem kopf

    // header1.h
    
    void funktion1();
    void funktion2();
    void funktion3();
    
    // header1.cpp
    
    funktion1()
    {
       funktion3(); // sollte das so sein? ansonsten versteh ich das nicht :D
    }
    
    funktion2()
    {
       // tu was
    }
    


  • Wenn ich dich richtig verstanden habe soll einfach jedes Objekt beim Erzeugen eine ID bekommen?

    Header

    class a
    {
    private:
        int m_ID;
    
        int GenerateID();
    
    public:
        a();
        int GetID();
    };
    

    Cpp

    #include "a.h"
    
    a::a()
    {
        m_ID = a::GenerateID();
    }
    
    int a::GenerateID()
    {
        // hier dein code zum erzeugen einer ID z.B.
        static int i = 0;
        return i++;
    }
    
    int a::GetID()
    {
        return m_ID;
    }
    

    Grüße



  • Ist halt nicht atomic.
    Dazu gibts std::atomic.

    std::atomic_int id;
    int newId = ++id;
    

Log in to reply