Vererbung



  • danke für die hilfe 🙂

    aber jetzt meckert das programm rum, wenn ich die minimale Leihgebühr ausgeben will.

    Er sagt mir, dass irgendwas mit dem ostream nicht hinhaut:

    Unresolved external 'operator <<(_STL::basic_ostream<char, _STL::char_traits<char> >&, KFZ 😉



  • cout << "KFZ mit minimaler Leihgebühr: " << **iMin << endl;
    

    Kurt



  • jetzt meint er:
    E2094 'operator<<' ist im Typ 'ostream' für Argumente des Typs 'KFZ' nicht implementiert

    ich werde noch wahnsinnig ^^



  • Du hast zwar den operator<<(ostream&,Kfz*) als friend deiner Klasse deklariert, aber du hast ihn nicht definiert (sprich: Der Compiler weiß, daß es ihn gibt, aber nicht was er machen soll). Das führt dann zu dem genannten Linker-Fehler.
    Und einen operator<<(ostream&,Kfz&) gibt es überhaupt nicht, wie dein Compiler richtig erkannt hat.



  • also in etwa so?

    ostream& operator<<(ostream& out, KFZ* kfz)
    {
    string herst = (*kfz).hersteller;
    float leihg = (*kfz).leihgebuehr;
    out<<herst<<", "<<leihg;
    return out;
    }

    dann stürzt er aber mit der Fehlermeldung:

    "... Exeption der Klasse EAccess Violation aufgetreten ..."

    ab?!



  • In Deinem Programm oben

    Mr. Blonde schrieb:

    ich habe folgendes Programm geschrieben:

    // dekl.h
    
    class KFZ
    {
    private:
     string hersteller;
     float leihgebuehr;
    public:
     KFZ(string herst, float leihg);
     friend ostream& operator<<(ostream& out, KFZ* kfz); // <- hier
     virtual string status()=0;
    };
    

    Hast Du einen Ausgabe-Operator für KFZ* definiert, aber keine Implementierung hinzugefügt. D.h., wenn Du die Methode AUTOVERLEIHER::ausgabe() aufrufst - mit der Erweiterung der minimalen Leihgebühr oder nicht, spielt keine Rolle - so meckert der Linker zu Recht die fehlende Implementierung an.

    Überlicherweise schreibt man

    friend ostream& operator<<(ostream& out, const KFZ& kfz );
    

    also die Ausgabe der KFZ und nicht dessen Pointer. Eine Implementierung könnte dann so aussehen:

    ostream& operator<<(ostream& out, const KFZ& kfz )
        {
            kfz.print( out );
            return out;
        }
    

    und 'print' wird zu einer virtuellen Methode von KFZ

    class KFZ
    {
    protected:
        virtual void print( std::ostream& out ) =0; // pur virtual; muss überladen werden  
        // ...
    

    die von jeder abgeleiteten Klasse überschrieben werden muss. Z.B.:

    class PKW : public KFZ
    {
    protected:
        virtual void print( std::ostream& out )
        {
            out << "Pkw " << tueren << "'türig";
        }
    

    Der Aufruf der Ausgabe von einem Iterator aus list< KFZ* > ist dann so, wie schon von ZuK geschrieben.

    Gruß
    Werner



  • Sorry. Ich sollte genauer lesen bevor ich Unsinn poste.
    Kurt



  • ZuK schrieb:

    Sorry. Ich sollte genauer lesen bevor ich Unsinn poste.

    Hallo Kurt,

    behaupte einfach, Du hast mein Posting vorhergesehen ;). Dann passt es.

    Gruß
    Werner



  • Hallo, ich hab das Programm nochmal komplett umgemoddet:

    dekl.h

    #include <iostream>
    #include <list>
    #include <conio>
    #include <string>
    #include <vcl>
    
    class KFZ;
    
    class AUTOVERLEIHER
    {
     private:
      list<KFZ*>Kfzliste;
    
     public:
      ~AUTOVERLEIHER();
      void aufnehmen(KFZ* kzf);
      KFZ* getMinladekapa(float ladekapazitaet);
      float getMinausleihgeb();
      void  anzeigen();
      float getTueren();
    
    };
    
    class KFZ
    {
    private:
     string hersteller;
     float leihgebuehr;
    
    public:
     KFZ(const string& Kfzhersteller, float Kfzleihgeb);
     virtual ~KFZ(){};   //benötigt um basisklassen virtuell zu setzen
     void getProfil();
     float getleihgebuehr();
    
    };
    
    // Klasse PKW -> erbt von KFZ Hersteller und Leihgebuehr
    
    class PKW : public virtual KFZ
    {
    private:
    
     int tueren;
    
    public:
    
     PKW(int Pkwtueren, const string& hersteller, float leihgebuehr);
     virtual void getProfil();   //wird virtual gesetzt aufgrund der mehrfachvererbung
                                 //ohne mehrfachvererbung, müsste nur in der Basisklasse
                                 //getProfile auf virtual gesetzt werden
     int gettueren();
    
    };
    
    class LKW : public virtual KFZ
    {
    private:
     float ladekapazitaet;
    
    public:
     LKW(float LKWladekapazitaet, const string& hersteller, float leihgebuehr);
     virtual void getProfil();
     float getLadekapazitaet();
    };
    
    class KOMBI : public PKW, public LKW
    {
    public:
     KOMBI(const string& hersteller, float leihgebuehr, int tueren, float ladekapazitaet):
      KFZ(hersteller, leihgebuehr),PKW(tueren, hersteller, leihgebuehr), LKW(ladekapazitaet, hersteller, leihgebuehr){}
    };
    

    header:

    #include "dekl.h"
    #include <typeinfo>
    //#include <monsterKI.brain>
    
    KFZ::KFZ(const string& Kfzhersteller, float Kfzleihgeb)
    {
    this->hersteller = Kfzhersteller;
    this->leihgebuehr = Kfzleihgeb;
    }
    
    void KFZ::getProfil()
    {
    string TypeName = typeid(*this).name();
    cout<<TypeName<<endl;
    cout<<"Hersteller: "<<this->hersteller<<" Leihgebuehr: "<<this->leihgebuehr;
    }
    
    float KFZ::getleihgebuehr()
    {
    return (this->leihgebuehr);
    }
    
    PKW::PKW(int Pkwtueren, const string& hersteller, float leihgebuehr) :
     KFZ(hersteller, leihgebuehr)
    {
    this->tueren = Pkwtueren;
    }
    
    int PKW::gettueren()
    {
    return (this->tueren);
    }
    
    void PKW::getProfil()
    {
     KFZ::getProfil();
     cout<<" Tueren: "<<this->tueren<<endl;
    }
    // nächstes dingsbums
    
    LKW::LKW(float Lkwladekapazitaet, const string& hersteller, float leihgebuehr) :
     KFZ(hersteller, leihgebuehr)
    
    {
    this->ladekapazitaet = Lkwladekapazitaet;
    }
    
    float LKW::getLadekapazitaet()
    {
    return (this->ladekapazitaet);
    }
    
    void LKW::getProfil()
    {
     KFZ::getProfil();
     cout<<" Ladekapazitaet: "<<this->ladekapazitaet<<endl;
    }
    
    void AUTOVERLEIHER::aufnehmen(KFZ* kfz)
    {
     Kfzliste.push_back(kfz);
    }
    
    float AUTOVERLEIHER::getTueren()
    {
     float gte = 1000;
     list<KFZ*>::iterator beginn = Kfzliste.begin();
     list<KFZ*>::iterator ende = Kfzliste.end();
    
      for(list<KFZ*>::iterator iter=beginn; iter != ende; iter++)
      {
       PKW *pkw = dynamic_cast<PKW*>(*iter);
       if(pkw && ((*pkw).gettueren() < gte))
        {
         gte = (*pkw).gettueren();
        }
       }
      return gte;
    }
    
    void AUTOVERLEIHER::anzeigen()
    {
     list<KFZ*>::iterator beginn = Kfzliste.begin();
     list<KFZ*>::iterator ende = Kfzliste.end();
    
      for(list<KFZ*>::iterator iter=beginn; iter != ende; iter++)
      {
       (**iter).getProfil();
      }
    }
    
    AUTOVERLEIHER::~AUTOVERLEIHER()
    {
     list<KFZ*>::iterator beginn = Kfzliste.begin();
     list<KFZ*>::iterator ende = Kfzliste.end();
    
      for(list<KFZ*>::iterator iter=beginn; iter != ende; iter++)
      {
      delete *iter;
      }
     Kfzliste.clear();
    }
    
    //Minimale Leihgebühr
    
    float AUTOVERLEIHER::getMinausleihgeb()
    {
     float me = 1000;
     list<KFZ*>::iterator beginn = Kfzliste.begin();
     list<KFZ*>::iterator ende = Kfzliste.end();
    
      for(list<KFZ*>::iterator iter=beginn; iter != ende; iter++)
      {
       PKW *pkw = dynamic_cast<PKW*>(*iter);
       if(pkw && ((*pkw).getleihgebuehr() < me))
        {
         me = (*pkw).getleihgebuehr();
        }
       }
      return me;
    }
    

    main:

    #pragma hdrstop
    #include "impl.cpp"
    #pragma argsused
    
    int main(int argc, char* argv[])
    {
    
    AUTOVERLEIHER a1;
    
    PKW * p1 = new PKW(6, " BMW", 1500);
    PKW * p2 = new PKW(4, " Renault", 500);
    PKW * p3 = new PKW(2, " XXX", 3000);
    
    LKW *l1 = new LKW(50," LKW",400);
    LKW *l2 = new LKW(30," W",600);
    LKW *l3 = new LKW(2,"H",3000);
    
    KOMBI * k1 = new KOMBI("AK", 27.50,3,500);
    
    a1.aufnehmen(dynamic_cast<KFZ*>(p1));
    a1.aufnehmen(dynamic_cast<KFZ*>(p2));
    a1.aufnehmen(dynamic_cast<KFZ*>(p3));
    a1.aufnehmen(dynamic_cast<KFZ*>(l1));
    a1.aufnehmen(dynamic_cast<KFZ*>(k1));
    
    a1.anzeigen();
    
    cout<<a1.getTueren()<<endl;
    cout<<a1.getMinausleihgeb();
    
    getch();
    return 0;
    }
    

    nun meine frage: wie kann ich realisieren, dass ein KFZ mit einer Ladekapazität von z.B. 2 angezeigt wird?!

    thx im voraus 🙂



  • Mr. Blonde schrieb:

    nun meine frage: wie kann ich realisieren, dass ein KFZ mit einer Ladekapazität von z.B. 2 angezeigt wird?!

    Schlecht. Da die Klasse AUTOVERLEIHER nur eine liste von Pointern auf KFZ speichert kannst du auch nur auf Variablen und Methoden zugreifen die in KFZ vorhanden sind und KFZ weiss nichts von einer Ladekapazität.
    Du könntest eventuell KFZ eine pure virtuelle Methode getLadeKapazitaet() geben und bei PKW immer 0 zurückgeben.
    Kurt



  • mhhh ... kay

    hab nochmal ne frage:

    header:

    #include <string>
    #include <iostream>
    #include <stdio>
    #include <list>
    
    //hochschulangehörige
    class HA
     {
      public:
       HA(string Name, string Vorname);
       friend ostream& operator<<(ostream& out, HA * ha);
       virtual string status() = 0;
    
      private:
       string HAName;
       string HAVorname;
     };
    
    //studenten
    class S:public HA
     {
      public:
       S(string Name, string Vorname, int MatrikelNummer);
       int getMatrNr();
       string status();
    
      private:
       int matrNr;
    
     };
    
    //mitarbeiter
    class MA:public HA
     {
      public:
       float mg();
       string  status();
       MA(string Name, string Vorname, float Monatsgehalt);
      private:
       float monatsgehalt;
     };
    
    //hilfsklasse für suche nach matrikelnummer
    class Funktor
     {
      public:
       Funktor(MatrikelNummer);
       bool operator() (HA * ha);
    
      private:
       int matrNr;
     };
    
    //personalverwaltung
    class PV
     {
      public:
       void hinzu(string Name, string Vorname, int MatrikelNummer);
       void hinzu(string Name, string Vorname, float Monatsgehalt);
       void hinzu(HA * ha);
       void ausgabe();
       HA * maxMg();
       HA * sucheStudent(int MatrikelNummer);
       ~PV();
      private:
       list<HA *> PersonenListe;
     };
    

    dekl:

    #include "dekl.h"
    #include <string>
    #include <typeinfo>
    #include <vcl>
    
    //HOCHSCHULANGEHÖRIGER
    HA::HA(string Name, string Vorname)
     {
      this->HAName = Name;
      this->HAVorname = Vorname;
     }
    
     //MITARBEITER
    MA::MA(string Name, string Vorname, float Monatsgehalt) : HA(Name, Vorname)
     {
      this->monatsgehalt = Monatsgehalt;
     }
    
    float MA::mg()
     {
      return this->monatsgehalt;
     }
    string MA::status()
     {
      string typeInfo = typeid (*this).name();
      return typeInfo + " " + FloatToStr(this->monatsgehalt).c_str();
     }
    
     //STUDENT
    S::S(string Name, string Vorname, int MatrikelNummer):HA(Name, Vorname)
     {
      this->matrNr = MatrikelNummer;
     }
    
    int S::getMatrNr()
     {
      return this->matrNr;
     }
    
    string S::status()
     {
      string typeInfo = typeid(*this).name();
      return typeInfo + " " + IntToStr(this->matrNr).c_str();
     }
    
    //PERSONALVERWALTUNG
    //hinzufühen student
    void PV::hinzu(string Name, string Vorname, int MatrikelNummer)
     {
      this->PersonenListe.push_back(dynamic_cast<HA*>(new S(Name, Vorname, MatrikelNummer)));
     }
    
    //hinzufügen mitarbeiter
    void PV::hinzu(string Name, string Vorname, float Monatsgehalt)
     {
      this->PersonenListe.push_back(dynamic_cast<HA*>(new MA(Name, Vorname, Monatsgehalt)));
     }
    
    //ha hinzufügen
    void PV::hinzu(HA * ha)
     {
      PersonenListe.push_back(ha);
     }
    
    //ausgabe der kompletten hochschulangehörigenliste
    void PV::ausgabe()
     {
      list<HA*>::iterator beginn = this->PersonenListe.begin();
      list<HA*>::iterator ende   = this->PersonenListe.end();
    
      for (list<HA*>::iterator iter = beginn;iter!=ende;iter++)
            {
             cout<<*iter<<'\n'<<(*iter)->status()<<'\n';
            }
    
     }
    
    //suche maximales monatsgehalt
    HA * PV::maxMg()
     {
      HA * returnha=NULL;
      float MaxMG = -1;
      list<HA*>::iterator beginn = this->PersonenListe.begin();
      list<HA*>::iterator ende   = this->PersonenListe.end();
      for (list<HA*>::iterator iter = beginn;iter!=ende;iter++)
            {
             MA * ma = dynamic_cast<MA*>(*iter);
             if (ma && ((*ma).mg() > MaxMG))
              {
               MaxMG = (*ma).mg();
               returnha = *iter;
              }
            }
      return returnha;
     }
    
    //suche student über matrikelnummer
    HA * PV::sucheStudent(int MatrikelNummer)
     {
      Funktor Fkt(MatrikelNummer);
      list<HA*>::iterator iter = find_if(PersonenListe.begin(), PersonenListe.end(), Fkt);
      if (iter == PersonenListe.end() || iter == NULL) throw MatrikelNummer;
      else return *iter;
     }
    
    //destruktor personalverwaltung
    PV::~PV()
     {
      list<HA*>::iterator beginn = this->PersonenListe.begin();
      list<HA*>::iterator ende   = this->PersonenListe.end();
      for (list<HA*>::iterator iter=beginn; iter != ende; iter++)
       {
        delete *iter;
       }
      PersonenListe.clear();
     }
    
    //hilfsfunktion für suche matrikelnummer
    Funktor::Funktor(int MatrikelNummer)
     {
      this->matrNr = MatrikelNummer;
     }
    
    bool Funktor::operator() (HA * ha)
     {
      S * s = dynamic_cast<S*>(ha);
      if (s && (*s).getMatrNr()==this->matrNr)
       {
        return true;
       }
      return false;
     }
    
    //überladen ausgabeoperator -> ostream...
    ostream& operator<<(ostream& out, HA * ha)
     {
      string Name = (*ha).HAName;
      string Vorname = (*ha).HAVorname;
      out<<Name<<", "<<Vorname;
      return out;
     }
    

    main:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #include <iostream>
    #include <conio>
    #include <stdio>
    #include "impl.cpp"
    #pragma hdrstop
    
    #pragma argsused
    int main(int argc, char* argv[])
     {
    
    PV pv; //personalverwaltung schaffen
    
    //hinzufügen studenten
    pv.hinzu("Schulze","Edgar",970123);
    pv.hinzu("Werder","Jana",930897);
    pv.hinzu("Hartung","Mark",970235);
    
    //hinzufügen MA (durch float automatisch)
    pv.hinzu("Otto","Walter",(float)3500);
    pv.hinzu("Neumeier","Regina",(float)1000);
    pv.hinzu("Engelhardt","Barbara",(float)2500);
    
    //ausgeben aller hochschulangehöriger
    pv.ausgabe();
    
    if (pv.maxMg() != NULL)
     {
      printf("\n\nmax MG : ");
      cout<<pv.maxMg()<<endl<<endl;
     }
    
    //suche nach matrikelnummer und rückgabe 
    int MatrikelNummer = -1;
    cout<<"MatrikelNummer eingeben : ";
    cin>>MatrikelNummer;
    try {
         HA * ha = pv.sucheStudent(MatrikelNummer);
         cout<<ha;
        }
    catch (int e)
     { cout<<"kein Eintrag!"; }
    
     getch();
     return 0;
    
     }
    

    wie kann ich erreichen, dass ich nicht über die matrikelnummer den namen suchen kann, sondern über den namen die matrikelnummer - muss doch irgendwie machbar sein

    thx im voraus 🙂



  • Mr. Blonde schrieb:

    wie kann ich erreichen, dass ich nicht über die matrikelnummer den namen suchen kann, sondern über den namen die matrikelnummer - muss doch irgendwie machbar sein

    Indem du eine entsprechende Funktorklasse schreibst, die im Konstruktor den Namen übergeben bekommt - und dann die gefundenen Einträge nach Student castest.

    (PS: eine kleine Bitte: verwende bitte in Zukunft cpp-Tags statt cs-Tags, dann passt das auch mit dem Syntax-Highlighting ;))


Anmelden zum Antworten