PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Polymorphismus in Vektoren erlaubt?



lokicall
26-06-2009, 19:49
Folgendes Problem:

Gegegen acht Objekte(A-H) die alle von Objekt O erben und jeweils eine andere Methode m() implementieren(zT. auch andere Attribute). Nun will ich den Polymorphismus in einem Vektor nutzen.

Denkansatz:
vector<O> obj;
obj.push_back(new A()); ... obj.push_back(new H());

Alle Objekte(A-H) in den Vektor rein, um später dann obj.m() ausführen zu können. Ist das möglich?

panzi
26-06-2009, 23:07
Polymorphie geht nur über Pointer oder Referenzen. Ich würde hierbei sogar zu Smartpointer greifen, wenn das möglich ist.

anda_skoa
27-06-2009, 11:21
Im Grunde genommen hast du das auch schon in deiner Anfrage. d.h. die Objekte werden mit new angelegt, du hast lediglich noch eine falsche, inkompatible Vektor Deklaration.



vector<O*> obj;


Bei Call-by-Value, also wenn du weder Pointer noch Referenzen benutzt, wird ja eine Kopie des Objekts erstellt. Wenn das Ziel der Kopie vom Typ deiner Basisklasse ist, ist jede Kopie nur mehr eine Instanz dieser Klasse, nicht mehr irgendeiner Subklasse.
Das nennt man "Slicing"


Ciao,
_

lokicall
27-06-2009, 12:28
Weiter gehts.

Ich bekomme immer wieder Probleme in der Linkphase bzgl. Referenzauflösung und multiple Definitionen. Ein bissl Code zum erklären:

Aus O.h


#ifndef _O_H
#define _O_H

class O {
public:
virtual void m(void);
protected:
int memptr;
};

void O::m() {}
#endif


Aus A.h

#include "O.h"

class A: public O {
public:
A(int &memptr);
void m(void);
};




B.o:B.cpp:(.text+0x0): multiple definition of `O::m()'
A.o:A.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
mingw32-make: *** [prog] Error 1

Ich kann mit der Fehlermeldung nicht viel anfangen.

anda_skoa
27-06-2009, 14:59
Nachdem die Fehlermeldung B.cpp und A.cpp referenziert, kann man da nicht viel sagen.

Ist das hier direktes Copy&Paste oder könntest du in deinem Code eventuell einen Include-Guard falsch haben und sich so eine Methodendefinition in mehreren Übersetzungeinheiten finden?

Ciao,
_

lokicall
27-06-2009, 18:39
Der Compiler wollte m() als abstrakte Methode haben - typisch C++-Compiler, ausssagekräftige Fehlermeldungen sehen anders aus .

locus vivendi
27-06-2009, 21:01
Der Compiler wollte m() als abstrakte Methode haben - typisch C++-Compiler, ausssagekräftige Fehlermeldungen sehen anders aus
Mal abgesehen davon, dass diese Meldung vom Linker kommt, ist sie doch ziemlich aussagekräftig gewesen - "multiple definition of O::m()" - und tatsächlich hattest du ja auch eine Definition im Header. Und den Header hast du wahrscheinlich mehrfach eingebunden (evtl. indirekt), oder?

kater
28-06-2009, 09:31
Ihr habt Probleme :)

class O {
public:
virtual void m() = 0;

};

class A : public O {

public:
void m() {
cout << "In A\n";
}
};

class B : public O {

public:
void m() {
cout << "In B\n";
}
};

int main() {

vector<O*> vec;
vec.push_back(new A());
vec.push_back(new B());
vec.push_back(new A());

for(unsigned int i = 0; i < vec.size(); i++)
vec[i]->m();
return 0;
}

So ?

anda_skoa
28-06-2009, 15:54
Der Compiler wollte m() als abstrakte Methode haben

Das geht auch ohne abstrakte Methode, wie man durch entsprechende Änderung in katers Beispielcode leicht überprüfen kann.

Es ist nur wie auch bei normalen Methoden oder Funktionen darauf zu achten, dass die Symboldefinition nur in einer Objektdatei stattfindet (das virtual Schlüsselwort ändert an dieser Anforderung gar nichts).
Ob das nun durch eine Definition in einer .cpp Datei oder durch inline Definition in der Klassendeklaration erfolgt, spielt dabei keine Rolle.

Ciao,
_

panzi
28-06-2009, 16:48
Ihr habt Probleme :)

class O {
public:
virtual void m() = 0;

};

class A : public O {

public:
void m() {
cout << "In A\n";
}
};

class B : public O {

public:
void m() {
cout << "In B\n";
}
};

int main() {

vector<O*> vec;
vec.push_back(new A());
vec.push_back(new B());
vec.push_back(new A());

for(unsigned int i = 0; i < vec.size(); i++)
vec[i]->m();
return 0;
}

So ?

Nur ist darauf zu achten, dass man normalerweise die ganzen Objekte auch wieder manuell per delete freigeben muss, ansonsten hast ein fettes Speicherleck. Deswegen hab ich ja auch das mit den Smartpointern gemeint.