Problem mit Typneudefintion



  • Hey,
    ich probiere gerade ein bisschen mit Header Dateien rum und ich komm nicht drauf, wie ich diesen Fehlercode wegbekomme.

    Fehler C2011 "time_span": "struct" Typneudefinition MeinKalender

    Fehler C2011 "Meeting": "class" Typneudefinition MeinKalender

    Fehler C2011 "Calender": "class" Typneudefinition MeinKalender

    Laut Internet lässt sich das mit #pragma once oder #ifndef #endif lösen, allerdings habe ich diese Befehle in meinem Programm stehen.
    Hier der Code
    .cpp Datei:

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <stdlib.h>
    #include <ctime>
    #include <algorithm>
    #include "Kalender.h"
    using namespace std;
    
    struct time_span
    {
        int fHour;
        int fMinute;
        int uHour;
        int uMinute;
    };
    
    class Meeting {
    private:
        time_span meeting;
    public:
        //Termin erstellen ohne Abfrage
        time_span createMeeting(int fromHour,int fromMinute,int untilHour,int untilMinute)
        {   
            
            meeting.fHour = fromHour;
            meeting.fMinute = fromMinute;
            meeting.uHour = untilHour;
            meeting.uMinute = untilMinute;
            if (checkForAllowedNumber(meeting) == false) {
                cout << "Error Creating a meeting. Check your numbers!" << endl;
            }
            return meeting;
    
        }
        //Termin erstellen mit Abfrage
        time_span createMeeting()
        {
            cout << "Meeting:" << endl;
            cout << "from: " << endl;
            cin >> meeting.fHour;
            cin >> meeting.fMinute;
            cout << "until: " << endl;
            cin >> meeting.uHour;
            cin >> meeting.uMinute;
            if (checkForAllowedNumber(meeting) == false)
            {
                cout << "Error" << endl;
                createMeeting();
            }
            return meeting;
        }
        //Zufälligen Termin erstellen
        time_span createRandomMeeting() {
            meeting.fHour = rand() % 24;
            meeting.fMinute = rand() % 60;
            meeting.uHour = meeting.fHour + 1;
            meeting.uMinute = meeting.fMinute + 30; //90 Minuten pro Termin
            if (meeting.uHour >= 24 || meeting.uMinute >= 60)
            {
                createRandomMeeting();
            }
            if (checkForAllowedNumber(meeting) == false)
            {
                createRandomMeeting();
            }
    
            return meeting;
        }
        bool checkForAllowedNumber(time_span t)
        {
            if (t.fHour < 0 || t.fHour >= 24)
            {
                cout << "a" << endl;
                return false;
            }
            if (t.fMinute < 0 || t.fMinute >= 60)
            {
                cout << "b" << endl;
                return false;
            }
            if (t.uHour < 0)
            {
                cout << "c" << endl;
                return false;
            }
            if (t.fHour > t.uHour)
            {
                cout << "d" << endl;
                return false;
            }
            if (t.fHour == t.uHour && t.fMinute >= t.uMinute)
            {
                cout << "f" << endl;
                return false;
            }
            if (t.uMinute < 0)
            {
                cout << "e" << endl;
                return false;
            }
    
            return true;
        }
    };
    
    
    
    
    class Calender :public Meeting {
    private:
        vector<time_span> schedule;
        string nameOfOwner;
    public:
        string get_name() {
            return nameOfOwner;
        }
        void set_name(string name) {
            nameOfOwner = name;
        }
        vector <time_span> get_schedule() {
            return schedule;
        }
        //Terminkalender anzeigen lassen
        void showSchedule() {
            cout << endl;
            for (int i = 0; i < schedule.size(); i++)
            {
                cout
                << setw(2) << setfill('0') << schedule[i].fHour << ":"
                << setw(2) << setfill('0') << schedule[i].fMinute << " - "
                << setw(2) << setfill('0') << schedule[i].uHour << ":"
                << setw(2) << setfill('0') << schedule[i].uMinute
                << endl;
            }
            cout << endl;
         
        }
    
        //Terminkalender eingeben, mit Abfrage der Termine
        vector <time_span> fillSchedule()
        {
            for (int i = 0; i < schedule.size(); i++)
            {
                schedule[i] = createMeeting();
            }
            return schedule;
        }
        //Automatisch Terminkalender mit random Terminen erstellen
        vector <time_span> fillScheduleAutomatic(int numberOfMeetings)
        {
            for (int i = 0; i < numberOfMeetings; i++)
            {
                schedule[i] = createRandomMeeting();
            }
            return schedule;
            
        }
        //Sortieren
        vector <time_span> sortSchedule() {
            sort(schedule.begin(), schedule.end(), [](const time_span& a, const time_span& b) {
                if (a.fHour != b.fHour)
                    return a.fHour < b.uHour;
                else if (a.fMinute > b.fMinute)
                {
                    return a.fHour > b.uHour;
                }
                return true;
                });
            return schedule;
        }
    
    };
    

    .h Datei

    
    #ifndef KALENDER_H
    #define KALENDER_H
    
    using namespace std;
    
    
    struct time_span
    {
    	int fHour;
    	int fMinute;
    	int uHour;
    	int uMinute;
    };
    
    //Basisklasse - Termin
    class Meeting {
    private:
    	time_span meeting;
    public:
    	time_span createMeeting();
    	time_span createMeeting(int, int, int, int);
    	time_span createRandomMeeting();
    	bool checkForAllowedNumber(time_span);
    };
    
    
    
    //Unterklasse - Terminkalender
    class Calender :public Meeting {
    private:
    	vector <time_span> schedule;
    public:
    	string get_name();
    	void set_name(string);
    	vector <time_span> get_schedule();
    	void showSchedule();
    	vector <time_span> fillSchedule();
    	vector <time_span> fillScheduleAutomatic(int);
    	vector <time_span> sortSchedule();
    };
    
    
    
    
    #endif 
    

    main.cpp

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <stdlib.h>
    #include <ctime>
    #include <algorithm>
    #include "Kalender.h"
    using namespace std;
    
    int main() {
    	Calender a;
    	a.set_name("Hans");
            /...
    }
    

    Kann mir jemand sagen, wie ich die Fehlermeldung loswerde?



  • @mute7 sagte in Problem mit Typneudefintion:

    Kann mir jemand sagen, wie ich die Fehlermeldung loswerde?

    Lösch die Definition von time_span, Meeting und Calender aus der .cpp Datei raus.



  • Ich dachte die Klasse gehört in die cpp Datei. Wie kann ich denn Defintion einer Klasse rausnehmen?



  • Du verwendest in der CPP-Datei die sogenannte Inline-Definition, d.h. du hast sowohl Deklaration der Klasse als auch Definition der Memberfunktionen in einem Code-Block.

    Durch das Einbinden der Headerdatei (mittels #include "Kalender.h") brauchst du nur die explizite Definitionen der Memberfunktionen (mittels Angabe des Klassennamens und Bereichsoperators ::) in der CPP-Datei:

    time_span Meeting::createMeeting(int fromHour, int fromMinute, int untilHour, int untilMinute)
    {   
      // ...
    }
    
    // ...
    

    Kurze Memberfunktionen (wie Getter/Setter) könntest du dann als Inline-Funktionen auch in der Headerdatei belassen (würde ich aber aus Konsistenzgründen ersteinmal von abraten).

    PS: Und in der Headerdatei dann nur die anderen Headerdateien einbinden, welche auch wirklich dort benötigt werden (evtl. reichen auch Vorwärtsdeklarationen), nur in der CPP-Datei dann alle benötigten Headerdateien einbinden.

    Und niemals using namespace std; in einer Headerdatei verwenden! Entweder explizit std:: benutzen oder aber einzelne using std::...-Anweisungen (am besten in Zusammenspiel mit eigenem Namensbereich).



  • Ok, vielen Dank für die ausführliche Antwort, du hast mir sehr weitergeholfen und ich habe das Programm zum laufen bekommen 🙂
    Kannst du vielleicht nochmal genauer erklären, warum using namespace std in Header Dateien so schlimm ist?



  • Weil durch die Einbindung der Headerdatei dann alle Namen aus dem std-Namensbereich in den globalen Namensbereich gebracht werden, d.h. wenn eine andere Datei diese Headerdatei einbindet und man einen eigenen (oder aus einer anderen Bibliothek verwendeten) Typ mit zufällig gleichen Namen wie einer der std-Namen verwendet (es gibt viele Namen, offiziell 'Identifier' genannt, dort!), dann kommt es zu einem Kompilierfehler wegen doppelten Namen - ähnlich wie dein "Problem mit Typneudefinition" hier ;- ).

    Edit: Oder wenn du z.B. selber einen Typ so nennst, wie ein Name aus dem std-Namensbereich: Ideone-Code...


Anmelden zum Antworten