 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Allan Rydberg Guest
|
Posted: Thu Sep 14, 2006 7:37 pm Post subject: array aus unterschieldlichen klassen... |
|
|
hi
folgende situation: ich habe eine reihe von pointern
auf unterschiedliche klassen, also:
class_a *cla;
cla = new class_a;
class_b *clb;
clb = new class_b;
class_c *clc;
clc = new class_c;
class_d *cld;
cld = new class_d;
nun moechte ich (aus verschiedenen gruenden die ich hier
nicht erlaeutern will) einen array aus pointern machen,
damit ich die klassen spaeter auch ueber eine art index
aufrufen kann. also irgendwas in der art:
??pointer?? myClaArr[MAXCLASSES];
myClaArr[0] = cla;
myClaArr[1] = clb;
myClaArr[2] = clc;
myClaArr[3] = cld;
wie gesagt, damit moechte ich nachher ausser der direkten
adressierung clb->update(); auch die adressierung ueber den
array machen koennen:
int aktiv = 1;
myClaArr[aktiv]->update();
geht das ueberhaupt? ich hab irgendwie ein chaos mit den
adresse und dem array und drehe mich im kreis. wie macht
man das korrekt?
vielen dank. |
|
| Back to top |
|
 |
Klaus N. Guest
|
Posted: Thu Sep 14, 2006 10:29 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
moin
ich würde (falls das von der hierarchie her möglich ist, was ich von
deiner update-Funktion her glaube) eine abstrakte basisklasse machen
und dann einen array von pointern auf eben diese klasse, also:
class clAbstr
{
public:
virtual ?returnwert? update(?parameter?)=0;
};
class cla:public clAbstr
{
public:
virtual ?returnwert? update(?parameter?);
};
und dann:
abstr * myClaArr[MAXCLASSES]; |
|
| Back to top |
|
 |
Andreas Huennebeck Guest
|
Posted: Fri Sep 15, 2006 1:07 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Allan Rydberg wrote:
| Quote: | folgende situation: ich habe eine reihe von pointern
auf unterschiedliche klassen, also:
class_a *cla;
cla = new class_a;
class_b *clb;
clb = new class_b;
class_c *clc;
clc = new class_c;
class_d *cld;
cld = new class_d;
nun moechte ich (aus verschiedenen gruenden die ich hier
nicht erlaeutern will) einen array aus pointern machen,
damit ich die klassen spaeter auch ueber eine art index
aufrufen kann. also irgendwas in der art:
??pointer?? myClaArr[MAXCLASSES];
myClaArr[0] = cla;
myClaArr[1] = clb;
myClaArr[2] = clc;
myClaArr[3] = cld;
wie gesagt, damit moechte ich nachher ausser der direkten
adressierung clb->update(); auch die adressierung ueber den
array machen koennen:
int aktiv = 1;
myClaArr[aktiv]->update();
geht das ueberhaupt?
|
Ja, und nennt sich Polymorphie.
| Quote: | ich hab irgendwie ein chaos mit den
adresse und dem array und drehe mich im kreis. wie macht
man das korrekt?
|
Da alle Klassen die Funktion update() kennen (müssen), leitest
Du sie alle von einer ge,einsamen Basisklasse ab, die die
update() Funktion pur virtuell deklariert:
class class_base
{
public:
virtual void update() = 0;
}
class class_a: public class_base
{
public:
virtual void update();
}
class class_b: public class_base
{
public:
virtual void update();
}
usw. für alle weiteren Klassen. Verwendet wird das dann wie folgt:
class_base *myClaArr[MAXCLASSES];
myClaArr[0] = cla;
myClaArr[1] = clb;
myClaArr[2] = clc;
myClaArr[3] = cld;
int aktiv = 1;
myClaArr[aktiv]->update();
Falls myClaArr dynamisch wächst, solltest Du die Verwendung eines
STL-Containers (vector, deque) in Betracht ziehen.
Tschau
Andreas
--
Andreas Hünnebeck | email: acmh (AT) gmx (DOT) de
----- privat ---- | www : http://www.huennebeck-online.de
Fax/Anrufbeantworter: 0721/151-284301
GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc
PGP-Key: http://www.huennebeck-online.de/public_keys/pgp_andreas.asc |
|
| Back to top |
|
 |
Thomas Thiele Guest
|
Posted: Fri Sep 15, 2006 5:10 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Allan Rydberg schrieb:
[Array von Pointern von verschiedenen Klassen]
Du muss die Klassen von einer gemeinsamen Basis-Klasse ableiten.
Diese Basisklasse muss die aufzurufende Funktion enthalten.
Diese Funktion muss virtual deklariert sein. Sie kann in Base
implementiert sein
oder rein virtuell sein.
class Base{
public:
virtual void update1(){ /* mach was für Base */ }
virtual void update2() = 0; //pure virtual
}
class A : public Base{
public:
virtual void update1(){ /* mach was für A */ } //kann
überschrieben werden
virtual void update2(){ /* mach was für A */ } //muss
implementiert werden
}
class B : public Base{
public:
virtual void update1(){ /* mach was für B */ } //kann
überschrieben werden
virtual void update2(){ /* mach was für B */ } //muss
implementiert werden
}
etc.pp.
Und dann das Array aus Pointern auf Base.
Base * array[SIZE];
Dann geht.
array[0] = new A();
array[1] = new B();
array[0] -> update2();
array[1] -> update2();
usw...
Kleine Stolperfalle, wenn du virtual weglässt, dann ruft
array[0] -> update1(); nicht(!) A::update1(); auf, sondern
Base::update1(); |
|
| Back to top |
|
 |
Allan Rydberg Guest
|
Posted: Fri Sep 15, 2006 8:34 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
moin.
ich kann eben die klassen nicht umbauen oder umstrukturieren. dafuer
gibts schon zu viel code drumherum. der ist eben auch nicht von mir
und nicht wirklich uebersichtlich oder gut strukturiert, drum will
ich mir diesn 'overlay' als neuen interface fuer mich selbst machen.
ich weiss, clumsy und nicht elegant, aber fuer den vorliegenden fall
waere es eben die beste loesung. |
|
| Back to top |
|
 |
Thomas J. Gritzan Guest
|
Posted: Sat Sep 16, 2006 5:31 am Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Moin!
Allan Rydberg schrieb:
| Quote: | ich kann eben die klassen nicht umbauen oder umstrukturieren. dafuer
gibts schon zu viel code drumherum. der ist eben auch nicht von mir
und nicht wirklich uebersichtlich oder gut strukturiert, drum will
ich mir diesn 'overlay' als neuen interface fuer mich selbst machen.
|
Du hast also verschiedene Klassen, die nix miteinander zu tun haben (keine
Vererbung), willst sie aber in _ein_ Array packen und Funktionen aufrufen
können, die die Klassen gemein haben (sowas wie update()).
Wie wärs damit:
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
using boost::function;
using boost::bind;
struct classA
{
void update()
{
std::cout << "update classA" << std::endl;
}
};
struct classB
{
void update()
{
std::cout << "update classB" << std::endl;
}
};
struct object
{
object( shared_ptr<void> data_, function<void()> update_)
: data(data_), update(update_) {}
shared_ptr<void> data;
function<void()> update;
};
std::vector<object> myArray;
void callUpdate()
{
typedef std::vector<object>::iterator objItor;
for (objItor it = myArray.begin(); it != myArray.end(); it++)
it->update();
}
int main()
{
classA* a = new classA;
myArray.push_back( object(shared_ptr<void>(a), bind(&classA::update, a)) );
classB* b = new classB;
myArray.push_back( object(shared_ptr<void>(b), bind(&classB::update, b)) );
callUpdate();
}
Satt vector<> kannst du auch ein Array benutzen, und statt einer
for-Schleife kannst du auch über einen Index auf die Elemente zugreifen:
myArray[2].update();
Und der shared_ptr ruft dir auch den richtigen Destruktor auf.
--
Thomas
http://www.netmeister.org/news/learn2quote.html |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Sat Sep 16, 2006 4:30 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Allan Rydberg wrote:
| Quote: | ich kann eben die klassen nicht umbauen oder umstrukturieren. dafuer
gibts schon zu viel code drumherum. der ist eben auch nicht von mir
und nicht wirklich uebersichtlich oder gut strukturiert, drum will
ich mir diesn 'overlay' als neuen interface fuer mich selbst machen.
|
Wenn die Klassen nicht gerade PODs mit Leib und Seele sind, stört das
Hinzufügen einer weiteren Basisklasse im Allgemeinen nicht. Um eine
Methode "update()" aufrufen zu können, muss der Compiler nun mal wissen,
dass die Objekte eine "update()"-Methode haben.
Ansonsten musst du dir eine zweite Klassenhierarchie drumherum stricken:
Basisklasse, plus für jede deiner unverschwägerten Klassen eine weitere
Klasse, die deren update() aufrufen kann. Templates vereinfachen das:
class BasicUpdater {
public:
virtual ~BasicUpdater() { }
virtual void doUpdate() = 0;
};
template<typename T>
class Updater {
T& u;
public:
Updater(T& u) : u(u) { }
void doUpdate() { u.update(); }
};
template<typename T>
Updater<T>*
makeUpdater(T& t) {
return new Updater<T*>(t);
}
Und dein Array:
std::vector<BasicUpdater*> zeug;
classA* a = new classA();
classB* b = new classB();
zeug.push_back(makeUpdater(*a));
zeug.push_back(makeUpdater(*b));
Für ein echtes Programm wäre i.A. der std::vector noch irgendwie zu
wrappen, um Speicherfreigabe und Exception-Sicherheit zu gewährleisten.
Stefan
PS, du solltest mal deine Großmachtaste reparieren. |
|
| Back to top |
|
 |
Hubert Schmid Guest
|
Posted: Sat Sep 16, 2006 6:25 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Allan Rydberg <alrdbg (AT) resalehost (DOT) networksolutions.com> writes:
| Quote: | ich kann eben die klassen nicht umbauen oder umstrukturieren. dafuer
gibts schon zu viel code drumherum. der ist eben auch nicht von mir
und nicht wirklich uebersichtlich oder gut strukturiert, drum will
ich mir diesn 'overlay' als neuen interface fuer mich selbst machen.
|
Eine alternative Lösung, die bisher noch nicht genannt wurde: Du
kannst boost::variant verwenden, um verschiedene Typen (oder auch
Zeiger auf verschiedene Typen) in einem std::vector zu speichern. Da
sieht dann beispielsweise so aus:
#include <vector>
#include "boost/variant.hpp"
struct A { void update() { } };
struct B { void update() { } };
typedef boost::variant<A*, B*> Foo;
std::vector<Foo> foos;
Um die Update-Funktion aufrufen zu können benötigst du noch einen
Visitor:
struct Update : boost::static_visitor<>
{
template <class Type>
void operator()(Type* value) const
{
value->update();
}
};
Die folgende Zeile ruft die Update-Funktion auf, unabhängig davon, ob
ein A oder B gespeichert wurde:
boost::apply_visitor(Update(), foos[0]);
--
Hubert Schmid - http://www.z42.de |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Sun Sep 17, 2006 4:07 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
ich schrob:
| Quote: | class BasicUpdater {
public:
virtual ~BasicUpdater() { }
virtual void doUpdate() = 0;
};
template<typename T
class Updater
|
Hier fehlt natürlich noch ein
: public BasicUpdater
sonst hätten wir wieder die Ausgangssituation.
Stefan |
|
| Back to top |
|
 |
Bob Hairgrove Guest
|
Posted: Mon Sep 18, 2006 1:25 am Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Dazu kann ich nur das bestätigen, was alle anderen schon gesagt haben,
nur sollte man die folgenden wichtigen Punkte noch erwähnen:
(1) Arrays von *Objekten* verschiedener Typen, auch wenn sie
voneinander ableiten, sollten wegen des Slicing-Problems nie verwendet
werden -- dafür kann man problemlos ein Array von Zeigern auf eine
gemeinsame Basisklasse einsetzen (das wurde ja auch einige Male schon
empfohlen);
(2) Bei Verwendung von Zeigern auf eine gemeinsame Basisklasse in
einem Array muß meistens (aber nicht zwingend) dynamische Allozierung
und Zerstörung der dazugehörenden Objekte verwendet werden (d.h. "new"
und "delete" werden für die Lebensdauer der Objekte benutzt). Das hat
zur Folge, daß der Destruktor in der virtuellen Basisklasse ebenfalls
virtuell (d.h. mit dem Schlüsselwort "virtual") deklariert und
implementiert werden *muß* ... sonst verursacht es undefiniertes
Verhalten, wenn ein solcher Zeiger mit "delete" verwendet wird. Dabei
kann der Rumpf der Implementierung des Destruktors auch leer sein.
--
Bob Hairgrove
NoSpamPlease (AT) Home (DOT) com |
|
| Back to top |
|
 |
Ernst Murnleitner Guest
|
Posted: Mon Sep 18, 2006 3:20 am Post subject: Re: array aus unterschieldlichen klassen... |
|
|
| Quote: | ... daß der Destruktor in der virtuellen Basisklasse ebenfalls
virtuell (d.h. mit dem Schlüsselwort "virtual") deklariert und
implementiert werden *muß* ... sonst verursacht es undefiniertes
Verhalten, wenn ein solcher Zeiger mit "delete" verwendet wird. Dabei
kann der Rumpf der Implementierung des Destruktors auch leer sein.
|
Was meinst Du mit "verursacht undefiniertes Verhalten"? Meinst Du A)
unerwünscht, weil nicht alle Konstruktoren aufgerufen werden oder B)
undefiniert?
Mit A) meine ich, dass nur der Destruktor der Basisklasse aufgerufen
wird. Das wäre nicht weiter schlimm, wenn die Klasse selber keinen
Speicher mit new angefordert hätte.
B: Es wäre ziemlich übel, wenn undefiniertes Verhalten auftreten würde
und der Compiler das vorher durchgehen hätte lassen. Was soll den da
passieren? Oder würde der Speicher gar nicht vollständig freigegeben
(kann ich mir ja eigentlich nicht vorstellen, das wäre ganz ganz übel).
Ernst |
|
| Back to top |
|
 |
Thomas Thiele Guest
|
Posted: Mon Sep 18, 2006 5:14 am Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Bob Hairgrove schrieb:
| Quote: | Das hat
zur Folge, daß der Destruktor in der virtuellen Basisklasse ebenfalls
virtuell (d.h. mit dem Schlüsselwort "virtual") deklariert und
implementiert werden *muß* ... sonst verursacht es undefiniertes
Verhalten, wenn ein solcher Zeiger mit "delete" verwendet wird. Dabei
kann der Rumpf der Implementierung des Destruktors auch leer sein.
|
Das Verhalten ist nicht undefiniert, es ist definiert!
Und zwar wird bei
class A{
public:
A(){std::cout << "A::A()" << std::endl; }
~A(){std::cout << "A::~A()" << std::endl; }
};
class B : public A{
public:
B(){std::cout << "B:B()" << std::endl; }
~B(){std::cout << "B::~B()" << std::endl; }
};
Und dann:
A* a = new B;
delete a;
Nicht ~B() aufgerufen, sondern nur ~A(). D.h. falls B Speicher
dynamisch anfordert, wird dieser nicht freigegeben.
Falls ~A() virtual ist, dann wird erst ~B() und dann ~A() aufgerufen. |
|
| Back to top |
|
 |
Tibor Pausz Guest
|
Posted: Mon Sep 18, 2006 9:11 am Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Ernst Murnleitner schrieb:
| Quote: | B: Es wäre ziemlich übel, wenn undefiniertes Verhalten auftreten würde
und der Compiler das vorher durchgehen hätte lassen. Was soll den da
passieren? Oder würde der Speicher gar nicht vollständig freigegeben
(kann ich mir ja eigentlich nicht vorstellen, das wäre ganz ganz übel).
|
Der Fall B tritt ein, der Speicher wird nur unvollständig freigegeben
und/oder es passiert was ähnlich Unangenehmes. |
|
| Back to top |
|
 |
Thomas Thiele Guest
|
Posted: Mon Sep 18, 2006 2:23 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Ernst Murnleitner schrieb:
| Quote: | Oder würde der Speicher gar nicht vollständig freigegeben
(kann ich mir ja eigentlich nicht vorstellen, das wäre ganz ganz übel).
|
Wieso wäre das ganz übel?
Das ist Stand der aktuellen Software. Frag mal JAVA-Entwickler... |
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Mon Sep 18, 2006 7:57 pm Post subject: Re: array aus unterschieldlichen klassen... |
|
|
Thomas Thiele wrote:
| Quote: | Bob Hairgrove schrieb:
Das hat
zur Folge, daß der Destruktor in der virtuellen Basisklasse ebenfalls
virtuell (d.h. mit dem Schlüsselwort "virtual") deklariert und
implementiert werden *muß* ... sonst verursacht es undefiniertes
Verhalten, wenn ein solcher Zeiger mit "delete" verwendet wird. Dabei
kann der Rumpf der Implementierung des Destruktors auch leer sein.
Das Verhalten ist nicht undefiniert, es ist definiert!
|
Wo? |
|
| Back to top |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|