[c++] gleichnamiges Objekt unterschiedlicher Klassen mit Auswahl erstellen



  • Hey Leute,

    wie kann ich es anstellen mit einer Auswahl ein gleichnamiges Objekt unterschiedlicher Klassen zu erstellen?

    ich stelle mir das so vor:

    Wenn Eingabevar=1 dann erzeuge Objekt "ga(genome)" der klasse1
    Wenn Eingabevar=2 dann erzeuge Objekt "ga(genome)" der klasse2, usw.

    Klasse1- klasseN haben dieselbe Basisklasse

    Ich möchte dann im weiteren Quellcode auf das Objekt ga zugreifen...

    Grüße

    Guddy



  • Na mit einem Zeiger 💡



  • Ich habe ich mich zwar noch nicht lange mit C++ beschäftigt aber ich vermute mal, dass du einen Zeiger vom Typ der Basisklasse brauchst.
    Jede spezielle Klasse ist vom Typ der Vaterklasse!



  • ich kann aber von der basisklasse kein Objekt erzeugen.



  • class A{};
    class B : public A{};
    
    // ...
    
    A* moep = new B();
    

    Darauf achten das die entscheidenen Methoden virtuell sind.



  • ???

    Wie würde das in meinem Besispiel mit der Schleife aussehen?



  • Du hast zwar keine Schleife in deinem "Beispiel" aber naja:

    class A{};
    class B : public A{};
    class C : public A{};
    
    // ...
    
    A* moep = NULL;
    
    switch(Eingabevar)
    {
    case 1: moep = new B(); break;
    case 2: moep = new C(); break;
    default: // Fehlerbehandlung oder sowas
    }
    


  • Wenn ich den Code wie folgt anwende:

    GAGeneticAlgorithm* ga = NULL;
    cout << "Klasse 1 o. 2? ";
    int class_type(0);
    std::cin >> class_type;
    if (class_type == 1) ga = new GASimpleGA;
    else ga = new GASteadyGA;
    

    kommt folgender Fehler:

    no matching function for call to `GASimpleGA::
       GASimpleGA()'
    

    GAGeneticAlgorithm ist Basisklasse und GASimpleGA, GASteadyGA sind abgeleitet Klassen. Alle Klassen existieren in einer externen Bibliothek auf die ich zugreife.



  • no matching function for call to `GASimpleGA::
    GASimpleGA()'

    das heißt einfach nur das es für diese Klasse keinen Defaultconstruktor gibt... du musst beim Konstruieren des Objekts also die Paramater die erforderlich sind mit angeben



  • Hallo,

    das zu übergebende Argument ist ein Objekt namens genome

    GABin2DecGenome genome(map, objective);
    

    Wenn ich es wie folght einbinde:

    GAGeneticAlgorithm ga(genome) = NULL;
    cout << "Klasse 1 o. 2? ";
    int class_type(0);
    std::cin >> class_type;
    if (class_type == 1) ga(genome) = new GASimpleGA;
    else ga(genome) = new GASteadyGA;
    

    beklomme ich diese Fehler:

    Optimierer.C:214: error: cannot declare variable `ga' to be of type `
       GAGeneticAlgorithm'
    Optimierer.C:214: error:   because the following virtual functions are
       abstract:
    /smb_mnt/tgutjahr/p/groupdrives/oe624-lsk/Aktuell/dipl/08-gutjahr/programme/Optimierungsprogramm/Galib/galib247/include/ga/GABaseGA.h:133: error:
       virtual void GAGeneticAlgorithm::initialize(unsigned int)
    /smb_mnt/tgutjahr/p/groupdrives/oe624-lsk/Aktuell/dipl/08-gutjahr/programme/Optimierungsprogramm/Galib/galib247/include/ga/GABaseGA.h:134: error:
       virtual void GAGeneticAlgorithm::step()
    Optimierer.C:214: error: assignment (not initialization) in declaration
    Optimierer.C:218: error: no match for call to `(GAGeneticAlgorithm) (
       GABin2DecGenome&)'
    Optimierer.C:218: error: no matching function for call to `GASimpleGA::
       GASimpleGA()'
    /smb_mnt/tgutjahr/p/groupdrives/oe624-lsk/Aktuell/dipl/08-gutjahr/programme/Optimierungsprogramm/Galib/galib247/include/ga/GASimpleGA.h:24: error: candidates
       are: GASimpleGA::GASimpleGA(const GASimpleGA&)
    /smb_mnt/tgutjahr/p/groupdrives/oe624-lsk/Aktuell/dipl/08-gutjahr/programme/Optimierungsprogramm/Galib/galib247/include/ga/GASimpleGA.h:23: error:
                      GASimpleGA::GASimpleGA(const GAPopulation&)
    /smb_mnt/tgutjahr/p/groupdrives/oe624-lsk/Aktuell/dipl/08-gutjahr/programme/Optimierungsprogramm/Galib/galib247/include/ga/GASimpleGA.h:22: error:
                      GASimpleGA::GASimpleGA(const GAGenome&)
    Optimierer.C:219: error: no match for call to `(GAGeneticAlgorithm) (
       GABin2DecGenome&)'
    

    Was ist hier schief gelaufen??

    Grüße

    Guddy



  • Du machst grundsätzlich was falsch. Du hast die Klassen auch nicht geschrieben, oder?
    Ohne deren Signaturen kann ich dir da auch nicht weiterhelfen.



  • nein, die habe ich nicht geschrieben.

    GABin2Dec hat folgenden Code:

    #ifndef _ga_bin2dec_h_
    #define _ga_bin2dec_h_
    
    #include <ga/GA1DBinStrGenome.h>
    #include <ga/gabincvt.h>
    
    #ifdef max
    #undef max
    #endif
    
    #ifdef min
    #undef min
    #endif
    
    class GABin2DecPhenotypeCore {
    public:
      GABin2DecPhenotypeCore();
      GABin2DecPhenotypeCore(const GABin2DecPhenotypeCore&);
      virtual ~GABin2DecPhenotypeCore();
      GABin2DecPhenotypeCore& operator=(const GABin2DecPhenotypeCore&);
    
      unsigned int cnt;		// how many references to us?
      unsigned int csz;		// how big are the chunks we allocate?
      unsigned int n, N;		// how many phenotypes do we have? (real,alloc)
      unsigned short *nbits;	// number of bits that max/min get mapped into
      unsigned short *oset;		// offset of the nth gene
      float *minval, *maxval;	// min, max value of phenotype elem
      unsigned int sz;		// total number of bits required
    };
    
    class GABin2DecPhenotype {
    public:
      GABin2DecPhenotype() : core(new GABin2DecPhenotypeCore) {}
      GABin2DecPhenotype(const GABin2DecPhenotype& p) :
      core(new GABin2DecPhenotypeCore(*(p.core))) {}
      virtual ~GABin2DecPhenotype(){core->cnt -= 1; if(core->cnt==0){delete core;}}
      GABin2DecPhenotype & operator=(const GABin2DecPhenotype& p){
        if(&p != this) *core = *(p.core);
        return *this;
      } 
      GABin2DecPhenotype * clone() const {return new GABin2DecPhenotype(*this);}
      void link(GABin2DecPhenotype& p){
        core->cnt -= 1;
        if(core->cnt == 0) delete core;
        core=p.core; core->cnt += 1;
      }
      void add(unsigned int nbits, float min, float max);
      void remove(unsigned int which);
      unsigned int size() const {return core->sz;}
      unsigned int nPhenotypes() const {return core->n;}
      float min(int which) const {return core->minval[which];}
      float max(int which) const {return core->maxval[which];}
      int length(int which) const {return core->nbits[which];}
      int offset(int which) const {return core->oset[which];}
      int equal(const GABin2DecPhenotype&) const;
    
    protected:
      GABin2DecPhenotypeCore *core;
    };
    
    inline int 
    operator==(const GABin2DecPhenotype& a, const GABin2DecPhenotype& b) {
      return a.equal(b);
    }
    
    inline int 
    operator!=(const GABin2DecPhenotype& a, const GABin2DecPhenotype& b) {
      return (a.equal(b) ? 0 : 1);
    }
    
    /* ----------------------------------------------------------------------------
       The phenotype does reference counting, so we can make a copy of it for our
    own use and we don't have to worry about extra overhead.
    ---------------------------------------------------------------------------- */
    class GABin2DecGenome : public GA1DBinaryStringGenome {
    public:
      GADefineIdentity("GABin2DecGenome", GAID::Bin2DecGenome);
    
    public:
      GABin2DecGenome(const GABin2DecPhenotype & p,
    		  GAGenome::Evaluator f=(GAGenome::Evaluator)0,
    		  void * u=(void *)0) : 
      GA1DBinaryStringGenome(p.size(), f, u), ptype(new GABin2DecPhenotype(p)){
        comparator(DEFAULT_BIN2DEC_COMPARATOR);
        encoder(DEFAULT_BIN2DEC_ENCODER);
        decoder(DEFAULT_BIN2DEC_DECODER);
      }
      GABin2DecGenome(const GABin2DecGenome & orig) :
      GA1DBinaryStringGenome(orig.sz) {ptype=(GABin2DecPhenotype *)0; copy(orig);}
      GABin2DecGenome& operator=(const GAGenome& arg) {copy(arg); return *this;}
      virtual ~GABin2DecGenome(){delete ptype;}
      virtual GAGenome *clone(GAGenome::CloneMethod flag=CONTENTS) const ;
      virtual void copy(const GAGenome &);
    
    #ifdef GALIB_USE_STREAMS
      virtual int read (STD_ISTREAM &);
      virtual int write (STD_OSTREAM &) const;
    #endif
    
      virtual int equal(const GAGenome &) const;
      virtual int notequal(const GAGenome &) const;
    
      const GABin2DecPhenotype & phenotypes(const GABin2DecPhenotype & p);
      const GABin2DecPhenotype & phenotypes() const {return *ptype;}
      int nPhenotypes() const {return ptype->nPhenotypes();}
      float phenotype(unsigned int n, float val);
      float phenotype(unsigned int n) const;
    
      void encoder(GABinaryEncoder e){encode = e; _evaluated = gaFalse;}
      void decoder(GABinaryDecoder d){decode = d; _evaluated = gaFalse;}
    
    protected:
      GABin2DecPhenotype * ptype;
      GABinaryEncoder encode;	// function we use to encode the bits
      GABinaryDecoder decode;	// function we use to decode the bits
    };
    
    #endif
    

    den Code der GAGeneticAlgorithm- klasse hab ich leider nicht.



  • guddy schrieb:

    GAGeneticAlgorithm ga(genome) = NULL;
    

    Kannst du uns erzählen, was du mit dieser Zeile erreichen willst? Ganz ehrlich, wenn man das mit deinen vorherigen Posts vergleicht, ergibt sich der Eindruck, dass du versuchst Codefetzen zusammenzustückeln die du nichtmal im Ansatz verstehst.



  • Mir ist schon klar das ich nicht alles verstehe was in den einzelenen Klassen der Bibliothek steht die ich hier benutze. Aber muss ich das?

    Mein Programm, dass ich auf Grundlage der Bibliothek programmiert habe funktioniert bis jetzt tadellos. Nun möchte einfach eine Abfrage einbauen die mir die einfache Auswahl des Algorithmusobjektes ga ermöglicht.

    Es gibt hier zwei Algorithmenklassen, die sich beide aus der Basisklasse GAGeneticAlgortihm ableiten und zwar GASimpleGA und GASteadystateGA. die Constructors, die ich verwenden will sind : GASimpleGA (const GAGenome&) und GASteadyStateGA(GAGenome&). das zu erzeugende Algorithmusobjekt ga kann nun
    entweder der Klasse GASimpleGA oder GASteaadyGA angehören.
    Ich möchte als Argument dem Objekt ga das Objekt genome übergeben, welches der Klasse GABin2DecGenome (Hierachie ist : public GA1DStringGenome : public GABinaryString, public GAGenome) angehört. Diese Objekt genome habe ich vorher erzeugt. Der Sinn der Geschichte ist, dass ich alle folgenden public Funktionen der GAGeneticAlgorithm-Klasse mit dem Objekt ga nutzen will. Und das ohne den Code nochmal neu zu schreiben. Beispiel:

    ga.parameters (params);			//Parameterliste initialisieren
    ga.maximize();				//Minimiere die Zielfunktion
    ga.selectScores(GAStatistics::AllScores); // aufrufen aller Statistiken in neu erzeugteen Statistikobjekten
    
    /*Abfrage: startpop. einlesen? nein: ga.initialize. else: init pop*/
    /*anstatt des ga initialisierer den pop-initialisierer verwenden um startpopulation einzulesen? */			
    
    //Ga-Objekt initialisieren
    ga.initialize ();			//generiert die Ind. der 1. Gen.
    

    Ich hoffe das Problem ist jetzt etwas verständlicher formuliert.

    @pumuckl: mit dem code

    GAGeneticAlgorithm ga(genome) = NULL;
    

    wollte ich dem erzeugten Objekt den Wert Null zuweisen. ICh dachte ich wende den Code von Fellhuhn richtig an, tu ich aber anscheinend nicht.

    Ich bin auf jeden Fall noch Anfänger auf dem Gebiet...

    Grüße

    Guddy



  • guddy schrieb:

    Es gibt hier zwei Algorithmenklassen, die sich beide aus der Basisklasse GAGeneticAlgortihm ableiten und zwar GASimpleGA und GASteadystateGA. die Constructors, die ich verwenden will sind : GASimpleGA (const GAGenome&) und GASteadyStateGA(GAGenome&). das zu erzeugende Algorithmusobjekt ga kann nun
    entweder der Klasse GASimpleGA oder GASteaadyGA angehören.
    Ich möchte als Argument dem Objekt ga das Objekt genome übergeben, welches der Klasse GABin2DecGenome (Hierachie ist : public GA1DStringGenome : public GABinaryString, public GAGenome) angehört.

    GAGeneticAlgortihm *ga = NULL;
    if (wasauchimmer == 1) ga = new GASimpleGA(genome);
    else                   ga = new GASteadyStateGA(genome);
    ga->wasauchimmer();
    
    // ...
    delete ga;
    


  • guddy schrieb:

    Mir ist schon klar das ich nicht alles verstehe was in den einzelenen Klassen der Bibliothek steht die ich hier benutze. Aber muss ich das?

    Wenn du die Klassen so nutzt, wie sie sind, und nicht mehr veränderst, reicht es, wenn du weisst, was die Methoden machen. Du musst dazu nicht zwingend die interne Implementation kennen. Wenn du allerdings die Funktionen dieser Klassen erweitern willst (z.B. durch Vererbung), solltest du schon Bescheid über die Implementationen wissen.

    guddy schrieb:

    Ich bin auf jeden Fall noch Anfänger auf dem Gebiet...

    Dann empfehle ich dir, dich zuerst richtig in Klassen und Objektorientierung einzuarbeiten, bevor du mit Dingen wie genetischen Algorithmen arbeitest.

    Du kannst nämlich nicht einfach einer Instanz von GAGeneticAlgorithm einen Wert wie NULL zuweisen. Wenn schon, dann einem Zeiger. Mit solchen Dingen solltest du dich unbedingt noch genauer auseinandersetzen, sonst wirst du dauernd wieder auf Probleme stossen.



  • Super. Das funktioniert so wie ichs mir erhofft hatte. ICh danke allen für ihre mühe.

    Viele Grüße
    Guddy



  • guddy schrieb:

    Mir ist schon klar das ich nicht alles verstehe was in den einzelenen Klassen der Bibliothek steht die ich hier benutze. Aber muss ich das?

    Der Code den du gepostet hast war eine Deklaration einer Variable ga, deren Konstruktor du ein Objekt genome übergeben hast und gleichzeitig eine Zuweisung mit NULL. Später hast du (zumindest sieht der Code so aus) eine Funktion ga aufgerufen, der du wiederum das selbe Objket genome als Argument verpasst hast und hast dem Ergebnis dieser Funktion einen Wert zugewiesen. Okay, man kann es auch als aufruf des operator() auf ga interpretieren, dann hast du wenigstens keine Zuweisung an ein temporäres Objket.

    Alles in allem ist das aber schon aus C++-Sicht ziemlicher Humbug, da braucht man kein Verständnis der verwendeten Klassen zu haben. Mein Tip ist daher: setz dich mit den Sprachmitteln von C++ auseinander, damit du geposteten Code zumindest von der Semantik her verstehst und entsprechend umformen kannst um ihn selbst anzuwenden. Dass Copy&Paste-Kauderwelsch vom Compiler verstanden wird ist höchst unwahrscheinlich, dass es das tut was du möchtest erst recht 😉

    /edit: "dem erzeugten Objekt den Wert NULL zuweisen" - ein erster Ansatzpunkt wäre auf jeden Fall schonma, den unterschied zwischen Zeigern und Objekten kennezulernen 🙂


Anmelden zum Antworten