Konstruktor + Vererbung nicht direkt abgeleitet von Oberklasse!



  • CarstenJ schrieb:

    ich hab das nur überflogen, aber wärs nicht günstiger deine private Variablen protected zu machen?

    Nö, das ist nie gut. Es wäre günstiger stets alle protected-Variablen private zu machen.

    Grund: Warum machst Du Variablen private? Damit niemand Deine Invarianten verletzen kann. wenn Du sie jetzt protected machst muß ich halt erben um Deine Invarianten kaputt zu kriegen. Kein wirklich großes Hindernis. Uns sowas passiert vor Allem dann leicht, wenn der Source umfangreich ist oder nicht zur Verfügung steht. Also lieber ein ordentliches Interface mit Methoden für denjenigen bieten der davon erbt.

    MfG Jester



  • Welchen Compiler verwendest du? Das müsste Standard-C++ sein, lad dir evtl. nen neueren Compiler runter.

    mfg



  • Welchen Compiler verwendest du? Das müsste Standard-C++ sein, lad dir evtl. nen neueren Compiler runter.

    ich glaube nich dass es daran liegt!!!

    gcc version 3.3.3 20040412 (Gentoo Linux 3.3.3-r5, ssp-3.3-7, pie-8.7.5.3)

    sonst keine idee?



  • Kannst Du den überarbeiteten Source nochmal posten?



  • jep .. klar 🙂

    #include <iostream>
    
    using namespace std;
    
    // Oberklasse
    
    class person {
    	private:
    		char name;
    		int id;
    	public:
    		person(char name, int id);
    		void setID(int setI);
    		int getID();
    		void setName(char setN);
    		char getName();
    		virtual float bezahlung();
    };
    person::person(char name, int id) {
    	name = name;
    	id = id;
    }
    
    void person::setID(int setI) {
    	id = setI;
    }
    int person::getID() {
    	return id;
    }
    void person::setName(char setN) {
    	name = setN;
    }
    char person::getName() {
    	return name;
    }
    
    // Klasse Angestellter, abgeleitet von person
    class angestellter : public person {
    	private:
    
    	public:
    		float gehalt;
    		angestellter(char name, int id);
    		void setGehalt(float setG);
    		float getGehalt();
    		virtual float bezahlung();
    };
    angestellter::angestellter(char name, int id) : person(name,id){
    	//name = name;
    	//id = id;
    }
    void angestellter::setGehalt(float setG) {
    	gehalt = setG;
    }
    float angestellter::getGehalt() {
    	return gehalt;
    }
    float angestellter::bezahlung() {
    	return gehalt;
    }
    
    // Klasse Arbeiter, abgeleitet von person
    class arbeiter : public person {
    	private:
    		float stundenlohn;
    		float anzahlstunden;
    	public:
    		arbeiter(char name, int id);
    		void setStundenlohn(float setS);
    		float getStundenlohn();
    		void setAnzahlstunden(float setA);
    		float getAnzahlstunden();
    		float bezahlung();
    };
    arbeiter::arbeiter(char name, int id) : person(name,id){
    	//name = name;
    	//id = id;
    }
    void arbeiter::setStundenlohn(float setS) {
    	stundenlohn = setS;
    }
    float arbeiter::getStundenlohn() {
    	return stundenlohn;
    }
    void arbeiter::setAnzahlstunden(float setA) {
    	anzahlstunden = setA;
    }
    float arbeiter::bezahlung() {
    	return stundenlohn*anzahlstunden;
    }
    
    // Klasse Verkaeufer, abgeleitet von angestellter!
    class verkaeufer : public angestellter {
    	private:
    		float provision;
    	public:
    		verkaeufer(char name, int id);
    		void setGehalt(float setG);
    		float getGehalt();
    		void setProvision(float setP);
    		float getProvision();
    		float bezahlung();
    };
    verkaeufer::verkaeufer(char name, int id) : angestellter(name,id){
    	//name = name;
    	//id = id;
    } 
    void verkaeufer::setGehalt(float setG) {
    	gehalt = setG;
    }
    float verkaeufer::getGehalt() {
    	return gehalt;
    }
    void verkaeufer::setProvision(float setP) {
    	provision = setP;
    }
    float verkaeufer::getProvision() {
    	return provision;
    }
    float verkaeufer::bezahlung() {
    	return gehalt+provision;
    }
    
    int main() {
    	angestellter ang1('a',0);
    	arbeiter arb1('b',1);
    	verkaeufer ver1('c',2);
    
    	ang1.setGehalt(2450.23);
    	cout << "gehalt von angestellter: " << ang1.bezahlung() << endl;
    
    	arb1.setStundenlohn(12.92);
    	arb1.setAnzahlstunden(38.5);
    	cout << "gehalt von arbeiter: " << arb1.bezahlung() << endl;
    
    	ver1.setGehalt(3849.42);
    	ver1.setProvision(300.00);
    	cout << "gehalt von verkaeufer: " << ver1.bezahlung() << endl;
    }
    

    hier die zeile mitm fehler:

    verkaeufer::verkaeufer(char name, int id) : angestellter(name,id){ }
    

    wenn ich verkäufer von person ableite is das alles kein ding, aber wenn ichs von angesteller ableite kommt das prob dass er das nich übergeben will eben! also ein objekt erzeugen und name,id übergeben!



  • ok, am GCC wirds kaum liegen.

    Argh, aber du hast keinen virtuellen Destruktor in den Basisklassen



  • Argh, aber du hast keinen virtuellen Destruktor in den Basisklassen

    brauch ich eigentlich auch nich, wofür denn? also ich habs so testhalber mal probiert, is aber noch der gleiche fehler! irgendwas läuft da falsch 😞



  • Also nen virtuellen Destruktor solltest Du auf jeden Fall noch nachrüsten, wenn Du schon ne virtuelle Funktion hast.

    Kann es sein, daß bezahlung (abgesehen davon ist das kein schöner Name für ne Methode, da kein Verb dabei ist) in der Klasse person nicht definiert ist? Dann mußt Du entweder rein virtuell machen (mit =0 hinter der Deklaration) oder ne Implementierung mit reinbauen.

    MfG Jester



  • Argh, aber du hast keinen virtuellen Destruktor in den Basisklassen

    brauch ich eigentlich auch nich, wofür denn?

    Zum Beispiel damit das Löschen eines abgeleiteten Objekts über einen Basisklassenzeiger nicht zu undefiniertem Verhalten führt.

    Also wenn das hier:

    /tmp/ccvRgTYT.o(.text+0x11): In function person::person[not-in-charge](char, int)': : undefined reference tovtable for person'
    /tmp/ccvRgTYT.o(.text+0x29): In function person::person[in-charge](char, int)': : undefined reference tovtable for person'
    /tmp/ccvRgTYT.o(.gnu.linkonce.r._ZTI12angestellter+0x8): undefined reference to typeinfo for person' /tmp/ccvRgTYT.o(.gnu.linkonce.r._ZTI8arbeiter+0x8): undefined reference totypeinfo for person'
    collect2: ld returned 1 exit status

    immer noch dein Problem ist, dann hast du scheinbar alle virtuellen Methoden in einer h-Datei definiert.
    Einige Compiler packen die vtable einer Klasse nun aber in die *cpp*-Datei, in der sie die erste nicht-inline Definition einer virtuellen Methode finden (besser gesagt in die daraus resultierende obj-Datei). Gibt es keine solche cpp-Datei, dann generieren sie keine vtable und keine Typinformationen -> Linkerfehler.
    Lösung: Zur h-Datei eine cpp-Datei anlegen und dort eine virtuelle Funktion der Klasse (z.B. den Dtor) definieren.



  • ja die meldung is noch mein problem! äh, ich hab bis jetzt erstma alles in einer cpp datei gelassen .. 🙄

    aber ihr seid euch einig, dass

    verkaeufer::verkaeufer(char name, int id) : angestellter(name,id){ }
    

    richtig ist??


Anmelden zum Antworten