vererbung[gelöst]



  • ich dachte das virtual bedeutet, dass sie abstrakt ist. also brauche ich es in der basisklasse ja auch nicht definieren, würde ja keinen sinn machen?

    hab jetzt mal alles umstruktoriert:

    uebung10.cpp

    #include "stdafx.h"
    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    #include "ICEAH_Moebel.h"
    using namespace std;
    //int ICEAH_Artikel::count = 0; 
    int _tmain(int argc, _TCHAR* argv[])
    {
    	return 0;
    }
    

    iceah artikel.h

    #include <iostream>
    #include <string>
    using namespace std;
    class ICEAH_Artikel{
    public:
    	static int count;
    	string name;
    	string beschreibung;
    	virtual string LangeBeschreibung();
    	ICEAH_Artikel();
    };
    

    iceah_moebel.h

    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    using namespace std;
    
    class ICEAH_Moebel {
    public:
    	string LangeBeschreibung();
    	ICEAH_Moebel() ;
    };
    

    die jweiligen c++ dateien:

    #include "stdafx.h"
    #include "ICEAH_Moebel.h"
    
    	string ICEAH_Moebel::LangeBeschreibung(){
    	return "blablalba";
    	}
    	ICEAH_Moebel::ICEAH_Moebel() : ICEAH_Artikel(){
    		//ICEAH_Artikel::count++;
    	}
    
    #include "stdafx.h"
    #include "ICEAH_Artikel.h"
    ICEAH_Artikel::ICEAH_Artikel(){
    		count++;
    }
    int ICEAH_Artikel::count = 0;
    

    hab soweit es ging alles behoben, was ich gefunden hab. gibt immer noch 2 fehler:

    Fehler 1 error C2011: 'ICEAH_Artikel': 'class' Typneudefinition c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_artikel.h 4

    Fehler 2 error C2614: 'ICEAH_Moebel': Unzulässige Elementinitialisierung: 'ICEAH_Artikel' ist weder Basis noch Element c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_moebel.cpp 7



  • Rustyspoon schrieb:

    ich dachte das virtual bedeutet, dass sie abstrakt ist.
    also brauche ich es in der basisklasse ja auch nicht definieren, würde ja keinen sinn machen?

    Nein. Virtual ist eine Voraussetung, um eine Funktion abstrakt zu machen. Das heißt nicht: virtual == abstrakt:

    class xyxx
    {
      type normaleMemberFunk();
      virtual type virtuelleMemberFunk();
      virtual type abstrakteMemberFunk() = 0;
      type falscheMemberFunk() = 0;   // das geht nicht.
    };
    

    Rustyspoon schrieb:

    hab jetzt mal alles umstruktoriert:

    uebung10.cpp

    #include "stdafx.h"
    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    #include "ICEAH_Moebel.h"
    using namespace std;
    //int ICEAH_Artikel::count = 0; 
    int _tmain(int argc, _TCHAR* argv[])
    {
    	return 0;
    }
    

    iceah artikel.h

    #include <iostream>
    #include <string>
    using namespace std;
    class ICEAH_Artikel{
    public:
    	static int count;
    	string name;
    	string beschreibung;
    	virtual string LangeBeschreibung();
    	ICEAH_Artikel();
    };
    

    iceah_moebel.h

    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    using namespace std;
    
    class ICEAH_Moebel {
    public:
    	string LangeBeschreibung();
    	ICEAH_Moebel() ;
    };
    

    die jweiligen c++ dateien:

    #include "stdafx.h"
    #include "ICEAH_Moebel.h"
    
    	string ICEAH_Moebel::LangeBeschreibung(){
    	return "blablalba";
    	}
    	ICEAH_Moebel::ICEAH_Moebel() : ICEAH_Artikel(){
    		//ICEAH_Artikel::count++;
    	}
    
    #include "stdafx.h"
    #include "ICEAH_Artikel.h"
    ICEAH_Artikel::ICEAH_Artikel(){
    		count++;
    }
    int ICEAH_Artikel::count = 0;
    

    hab soweit es ging alles behoben, was ich gefunden hab. gibt immer noch 2 fehler:

    Fehler 1 error C2011: 'ICEAH_Artikel': 'class' Typneudefinition c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_artikel.h 4

    Das passiert gerne, wenn Header andere HEader includieren. Abhilfe:

    #ifndef HEADER_NAME_H
    #define HEADER_NAME_H
    
    ...
    
    #endif
    

    Wenn Du Dir sowas um deine eigentliche Header angewöhnst, kannst Du effektiv verhindern, daß der Präprozessor eine HEaderdatei zweimal einfügt und Du Dir um die Reihenfolge der includes keine Gedanken machen mußt.

    Rustyspoon schrieb:

    Fehler 2 error C2614: 'ICEAH_Moebel': Unzulässige Elementinitialisierung: 'ICEAH_Artikel' ist weder Basis noch Element c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_moebel.cpp 7

    Wohl etwas zuviel umstrukturiert. Du hast die Basis "wegoptimiert".

    mfg Martin



  • #ifndef HEADER_NAME_H
    #define HEADER_NAME_H
    
    ...
    
    #endif
    

    sowas änliches hab ich schonmal gesehen aber wie genau setze ich das ein?
    einfach header_name_h durch zb ICEAH_Artikel.h austauschen und damit die .h datei "umklammern" ?

    Wohl etwas zuviel umstrukturiert. Du hast die Basis "wegoptimiert".

    ja, wegoptimiert find ich gut! nur wie stelle ich solch eine basisklasse wieder her, ich dachte bei c++ kann man klassen einfahc implementieren, hab doch vorher auch nciht gesagt "so das ist jetzt ne basisiklasse"

    Gruß



  • Rustyspoon schrieb:

    #ifndef HEADER_NAME_H
    #define HEADER_NAME_H
    
    ...
    
    #endif
    

    sowas änliches hab ich schonmal gesehen aber wie genau setze ich das ein?
    einfach header_name_h durch zb ICEAH_Artikel.h austauschen und damit die .h datei "umklammern" ?

    Genau.

    Rustyspoon schrieb:

    Wohl etwas zuviel umstrukturiert. Du hast die Basis "wegoptimiert".

    ja, wegoptimiert find ich gut! nur wie stelle ich solch eine basisklasse wieder her, ich dachte bei c++ kann man klassen einfahc implementieren, hab doch vorher auch nciht gesagt "so das ist jetzt ne basisiklasse"

    Gruß

    Äh, warum nicht so, wie in Deinem ersten Beispiel?

    class ICEAH_Moebel : public ICEAH_Artikel{
    

    Das geht in Headerdateien genauso.

    Einer Klasse sagt man nicht: Du bist jetzt 'ne Basisklasse. Eine Klasse wird zu einer Basisklasse in dem Du der abgeleiteten Klasse sagt, Deine Basisklasse ist xyz.

    mfg Martin



  • class ICEAH_Moebel : public ICEAH_Artikel{
    ....
    

    so steht schon in meiner moebel.h hatte ich wohl mitlerweile selber gefunden.

    aber hab noch 2 fehler:

    Fehler 2 error C2504: 'ICEAH_Artikel': Basisklasse undefiniert c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_moebel.h 7
    Fehler 1 error C2011: 'ICEAH_Artikel': 'class' Typneudefinition c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_artikel.h 4



  • Rustyspoon schrieb:

    class ICEAH_Moebel : public ICEAH_Artikel{
    ....
    

    so steht schon in meiner moebel.h hatte ich wohl mitlerweile selber gefunden.

    aber hab noch 2 fehler:

    Fehler 2 error C2504: 'ICEAH_Artikel': Basisklasse undefiniert c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_moebel.h 7

    lass mal das

    using namespace std;
    

    weg und schreibe dafür statt string std:string. Ich bin mir jetzt nicht sicher, aber das könnte die Ursache sein, wenn Dein Quelltext wirklich so ausschaut, wie Du's hier gepostet hast.

    Rustyspoon schrieb:

    Fehler 1 error C2011: 'ICEAH_Artikel': 'class' Typneudefinition c:\dokumente und einstellungen\tim\eigene dateien\visual studio 2008\projects\aufgabenueberarbeitet\uebung 11\iceah_artikel.h 4

    Hast Du meinen Tipp mit

    #ifndef xxx
    #define xxx
    ...
    #endif
    

    auch brav umgesetzt? Sorge auch dafür, daß das Makro eindeutig ist.

    mfg Martin



  • das using namespace std hat nichts veränder.

    durch das define sind neue fehler aufgetreten.

    ich poste nochmal den jetzigen code

    iceah_moebel.h

    #ifndef ICEAH_Moebel_h
    #define ICEAH_Moebel_h
    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    
    class ICEAH_Moebel : public ICEAH_Artikel{
    public:
    	std::string LangeBeschreibung();
    	ICEAH_Moebel() ;
    };
    #endif
    

    iceah_artikel.h

    #ifndef ICEAH_Artikel_h
    #define ICEAH_Artikel_h
    #include <iostream>
    #include <string>
    
    class ICEAH_Artikel{
    public:
    	static int count;
    	std::string name;
    	std::string beschreibung;
    	virtual std::string LangeBeschreibung();
    	ICEAH_Artikel();
    };
    #endif
    

    iceah moebel.cpp

    #include "stdafx.h"
    #include "ICEAH_Moebel.h"
    
    std::string ICEAH_Moebel::LangeBeschreibung(){
    	return "blablalba";
    	}
    	ICEAH_Moebel::ICEAH_Moebel() : ICEAH_Artikel(){
    		//ICEAH_Artikel::count++;
    	}
    

    iceah artikel.cpp

    #include "stdafx.h"
    #include "ICEAH_Artikel.h"
    ICEAH_Artikel::ICEAH_Artikel(){
    		count++;
    }
    int ICEAH_Artikel::count = 0; 
     std::string ICEAH_Artikel::LangeBeschreibung(){
    return "schalala";
    }
    

    main

    #include "stdafx.h"
    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    #include "ICEAH_Moebel.h"
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    //	ICEAH_Moebel IM;
    	return 0;
    }
    

    edit:
    achja, hier die eigentliche aufgabe, falls es jemanden interessiert

    Aufgabe 1
    Folgende Punkte sollen zunächst umgesetzt werden:
    a) Entwurf einer abstrakten Basisklasse ICEAH_Artikel mit zwei Attributen Name und
    Beschreibung (z.B. Name “AOSELE“, Beschreibung „Tischleuchte“). Zusätzlich soll
    diese Klasse in einer statischen Variable Anzahl mitzählen, wie viele Objekte gerade
    existieren. Zur ausführlichen Beschreibung spendieren Sie noch eine rein virtuelle
    Funktion LangeBeschreibung, die in abgeleiteten Klassen implementiert werden soll.
    b) Entwurf zweier von der Basisklasse ICEAH_Artikel abgeleiteten Klassen:
    ICEAH_Moebel und ICEAH_Zubehoer. Artikel, deren Beschreibung „Stuhl“, „Tisch“
    oder „Schrank“ enthält, sollen (in Aufgabe 2) durch Objekte der Möbelklasse
    repräsentiert werden. Die Zubehörklasse repräsentiert alle anderen Artikel. Ebenfalls
    sollen diese Klassen in statischen Variablen mitzählen, wie viele Objekte jeweils gerade
    existieren.

    Gruß



  • Rustyspoon schrieb:

    das using namespace std hat nichts veränder.

    durch das define sind neue fehler aufgetreten.

    Schreibe statt

    #ifndef ICEAH_Moebel.h
    #define ICEAH_Moebel.h

    #ifndef ICEAH_Moebel**h
    #define ICEAH_Moebel
    **h

    Punkte sind auch bei Makros nicht erlaubt.

    Rustyspoon schrieb:

    ich poste nochmal den jetzigen code

    iceah_moebel.h

    #ifndef ICEAH_Moebel.h
    #define ICEAH_Moebel.h
    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    
    class ICEAH_Moebel : public ICEAH_Artikel{
    public:
    	std::string LangeBeschreibung();
    	ICEAH_Moebel() ;
    };
    #endif
    

    iceah_artikel.h

    #ifndef ICEAH_Artikel.h
    #define ICEAH_Artikel.h
    #include <iostream>
    #include <string>
    
    class ICEAH_Artikel{
    public:
    	static int count;
    	std::string name;
    	std::string beschreibung;
    	virtual std::string LangeBeschreibung();
    	ICEAH_Artikel();
    };
    #endif
    

    iceah moebel.cpp

    #include "stdafx.h"
    #include "ICEAH_Moebel.h"
    
    std::string ICEAH_Moebel::LangeBeschreibung(){
    	return "blablalba";
    	}
    	ICEAH_Moebel::ICEAH_Moebel() : ICEAH_Artikel(){
    		//ICEAH_Artikel::count++;
    	}
    

    iceah artikel.cpp

    #include "stdafx.h"
    #include "ICEAH_Artikel.h"
    ICEAH_Artikel::ICEAH_Artikel(){
    		count++;
    }
    int ICEAH_Artikel::count = 0;
    

    main

    #include "stdafx.h"
    #include <string>
    #include <iostream>
    #include "ICEAH_Artikel.h"
    #include "ICEAH_Moebel.h"
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    //	ICEAH_Moebel IM;
    	return 0;
    }
    

    Du hast immer noch keine Definition von

    ICEAH_Artikel::LangeBeschreibung

    Du mußt das schon Umsetzen, was Dir gesagt wird.

    mfg Martin



  • ahh danke!

    jetzt copiliert der code. ich hab in meinem vorgangenen post mal meine code einträge soweit editiert wie ich es in echt gemacht habe.
    Was ich nicht genau verstehe ist, warum ich die abstrakte Funktion deklarieren muss?
    Ist das nicht das was ich garnicht will?
    ich meine Artikel hat kein genaue Beschreibung. Erst das moebelstück hat eine. Welches ja artikel ableitet?

    Gruß



  • Rustyspoon schrieb:

    ahh danke!

    jetzt copiliert der code.

    Na bitte. Geht doch. 👍

    Rustyspoon schrieb:

    ich hab in meinem vorgangenen post mal meine code einträge soweit editiert wie ich es in echt gemacht habe.
    Was ich nicht genau verstehe ist, warum ich die abstrakte Funktion deklarieren muss?
    Ist das nicht das was ich garnicht will?
    ich meine Artikel hat kein genaue Beschreibung. Erst das moebelstück hat eine. Welches ja artikel ableitet?

    Gruß

    Nun in Deiner konkreten Anwendung ist es wohl nicht erforderlich. Aber es ist so gefordert in der Aufgabenstellung. Allerdings ist es blöd formuliert. Was die mit "rein virtuell" meinten ist wohl, daß Du eine abstrakte Klasse definieren sollst. Damit kannst Du die Basisklasse nicht selbst instanzieren kannst aber trotzdem mit Zeigern darauf Memberfunktionen der abgeleiteten Klassen aufrufen:

    class base
    {
       virtual function() = 0;
    }
    
    class derived : public base
    {
       function();
    }
    
    int derived::function()
    {
       return 5;
    }
    
    int main( void )
    {
       base *x = new derived;
    
       cout << x->function();
    
       delete x;
    
       return 0;
    }
    

    function ist in base nur deklariert nicht aber definiert. Und weil es abstrakt ist, darfst Du auch keine Instanz von base erzeugen:

    base x;
    

    gibt einen Compilerfehler.

    Weil es aber virtuel ist, kannst Du es trotzdem über einen Zeige auf base aufrufen. Deine Anwendung entscheidet dann zur Laufzeit was aufgerufen werden soll.

    Bei diesem einfachen Beispiel ist es natürlich dumm. Aber stelle Dir mal vor Du schreibst eine Containerklasse, die verschiedene Zeiger speichern soll und über diese Zeiger bestimmte Methoden aufrufen soll. Der Container kennt aber unter Umständen nur die Basisklasse. Möglicherweise definiert die Basisklasse nur das Interface. Der Programmierer des Containers soll sich aber nicht mit der Implementierung der Memberfunktionen beschäftgen.

    Dazu definiert er eine abstrakte Klasse, die alle erforderlichen Funktionen kennt und gibt seinen Kolegen nur den Container und die Basisklasse. Die Kolegen erzeugen dann neue Klassen, die von der Basis abgeleitet sind, und übergeben dem Container Zeiger auf diese Klassen.

    mfg Martin



  • sauber!

    ich denke mal ich habs verstanden, echt top was du dir für ne mühe gegeben hast!

    Gruß


Anmelden zum Antworten