C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

array aus unterschieldlichen klassen...
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Allan Rydberg
Guest





PostPosted: Thu Sep 14, 2006 7:37 pm    Post subject: array aus unterschieldlichen klassen... Reply with quote



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





PostPosted: Thu Sep 14, 2006 10:29 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote



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





PostPosted: Fri Sep 15, 2006 1:07 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote



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





PostPosted: Fri Sep 15, 2006 5:10 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Fri Sep 15, 2006 8:34 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Sat Sep 16, 2006 5:31 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Sat Sep 16, 2006 4:30 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Sat Sep 16, 2006 6:25 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Sun Sep 17, 2006 4:07 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Mon Sep 18, 2006 1:25 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Mon Sep 18, 2006 3:20 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Mon Sep 18, 2006 5:14 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Mon Sep 18, 2006 9:11 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Mon Sep 18, 2006 2:23 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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





PostPosted: Mon Sep 18, 2006 7:57 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

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
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
 


Powered by phpBB © 2001, 2006 phpBB Group