Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Vector mit Objekten derselben Basisklasse

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
29.11.2006, 10:52 Uhr
Soto



Hallo,
ich möchte folgendes machen (und wüsste gern, ob es prinzipiell überhaupt möglich ist):

Von einer bestimmten Basisklasse B möchte ich mehrere Klassen K1, K2, K3 ableiten. Mein Ziel ist, einen Vektor zu definieren, der Elemente aus diesen Klassen K1, K2, K3 enthält. Geht das, indem ich den Vektor als einen Vektor von Objekten der Klasse B deklariere?

(Ich habe es bereits versucht und bei der Umsetzung Probleme, ich möchte nur wissen, ob es prinzipiell geht, vielleicht hat ja jemand Erfahrung damit?)

mfG,
Soto
--
ich versuche zu helfen, sorry wenn ich nen scheiß rede ^^
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.11.2006, 10:53 Uhr
J-jayz-Z
Perl Crack ala Carte
(Operator)


Wenn du von B ableitest kannst du auf jeden Fall nach B casten - also ja
--
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="66756e2d736f66742e6465"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.11.2006, 11:27 Uhr
ao

(Operator)


std::vector<B*>, so gehts.
std::vector<B> geht glaub ich nicht.

Oder lieg ich falsch?

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
29.11.2006, 11:51 Uhr
virtual
Sexiest Bit alive
(Operator)


Nein, die verwendung von std::vector<B> wäre eine ganz große Falle:

C++:
class Base {
};

class Derived: public Base {
};


std::vector<Base> v;

Derived d;

v.push_back(d);



Tut zwar auf den ersten Blick ein Derived in den Vector rein. Aber da beim einfügen eines Elements lediglich der Base Anteil in den Vektor tatsächlich kopiert wird, steht in v also nur ein Base drinnen.

Die Verwndung von Base* löst nun zwar dieses spezielle Problem, aber dann läuft man nunmehr in das Problem, daß die Destruktoren der Elemente von v nichtmehr korrekt aufgerufen werden. Daher nimmt man in der Regel eher smart-Pointer:

C++:
std::vector< smart_ptr<B> > v;



SmartPointer sind nicht Bestandteil des Standards. Unter Boost wirst Du jdoch fündig. Alternativ kannst Du ja mal auch in der FAQ gucken, da habe ich vor Zeiten mal eine SmartPointer Klasse reingepostet.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 29.11.2006 um 11:52 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
29.11.2006, 12:17 Uhr
J-jayz-Z
Perl Crack ala Carte
(Operator)



C++:
#include <iostream>
#include <vector>

class First
{
public:
    First() { }
    void out()
    {
        std::cout << "Ich bin a" << std::endl;
    }

    void bla()
    {
        std::cout << "überall..." << std::endl;
    }
};

class Second : public First
{
public:
    Second() { }
    void out()
    {
        std::cout << "Ich bin b" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    First *first = new First();
    Second *second = new Second();
    std::vector<First *> *vec = new std::vector<First *>();
    vec->push_back(first);
    vec->push_back(second);
    (vec->at(0))->out();
    (vec->at(1))->out();
    std::cin.get();
    return EXIT_SUCCESS;
}

Ausgabe:

Code:
Ich bin a
Ich bin a

Der Grund dafür ist, das gecastet wird. Somit wird Second durch das Einfügen in den Vector wieder First.Eine Lösung wäre evtl. 2 Vectoren zu erstellen und diese in einer extra Klasse zu sichern:

C++:
#include <iostream>
#include <vector>

class First
{
public:
    First() { }
    void out()
    {
        std::cout << "Ich bin a" << std::endl;
    }

    void bla()
    {
        std::cout << "überall..." << std::endl;
    }
};

class Second : public First
{
public:
    Second() { }
    void out()
    {
        std::cout << "Ich bin b" << std::endl;
    }
};

class Third
{
private:
    std::vector<First> firstVec;
    std::vector<Second> secondVec;
public:
    std::vector<First> getFirstVector()
    {
        return this->firstVec;
    }

    std::vector<Second> getSecondVector()
    {
        return this->secondVec;
    }

    void setVector(std::vector<First> firstVecP)
    {
        this->firstVec = firstVecP;
    }

    void setVector(std::vector<Second> secondVecP)
    {
        this->secondVec = secondVecP;
    }
};

int main(int argc, char* argv[])
{
    First first;
    Second second;
    Third third;
    std::vector<First> vecFirst;
    std::vector<Second> vecSecond;
    vecFirst.push_back(first);
    vecSecond.push_back(second);
    third.setVector(vecFirst);
    third.setVector(vecSecond);
    //Zugriff:

    (third.getFirstVector()).at(0).out();
    (third.getSecondVector()).at(0).out();

    std::cin.get();
    return EXIT_SUCCESS;
}


Die Klasse Third kannst du dann in deinen Vector packen und darin mit First und Second arbeiten
--
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="66756e2d736f66742e6465"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

Dieser Post wurde am 29.11.2006 um 12:19 Uhr von J-jayz-Z editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
29.11.2006, 13:01 Uhr
stephanw
localhorst



Zitat von virtual:
Die Verwndung von Base* löst nun zwar dieses spezielle Problem, aber dann läuft man nunmehr in das Problem, daß die Destruktoren der Elemente von v nichtmehr korrekt aufgerufen werden.

Warum das denn ? Wenn Base eine Basisklasse sein soll, von der abgeleitet werden soll/darf, dann sollte der Destruktor virtuell sein. Dann klappts auch mit dem Löschen.

C++:
class Base {
  virtual ~Base();
};

class Derived: public Base {
};


--
Reden ist Schweigen und Silber ist Gold.

Dieser Post wurde am 29.11.2006 um 13:02 Uhr von stephanw editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
30.11.2006, 08:48 Uhr
~Soto
Gast


Vielen Dank an alle für die rege Beteiligung

Mir persönlich gefällt die Lösung mit Zeigern auf die Basisklasse (und virtuellen Destruktoren in der Basisklasse) am besten - vermutlich werd ichs so machen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
30.11.2006, 09:44 Uhr
Soto



Nun hätte ich noch eine Frage:

Ich würde gerne eine Klasse C schreiben. Jedes Objekt der Klasse C soll einen Zeiger auf ein Objekt der (-mittlerweile- virtuellen) Klasse B enthalten.

Nun möchte ich gerne dieses Objekt der Klasse B im Konstruktor von C erzeugen lassen. Dazu verwende ich "new".


C++:
class C {
...

private:
  B* obj1;

public:
  C () {
    obj1 = new K1();
  }

...
};



(Ich habe es jetzt natürlich sehr vereinfacht skizziert.)
Der Compiler schreit nicht und das Programm lässt sich ausführen.

Trotzdem noch meine Frage: Ist das richtig, hier diesen new-Befehl zu verwenden? Kann ich sicher sein, dass der Speicherplatz von K1 nicht irgendwann verloren geht? (Ohne dass das Objekt der Klasse C gelöscht wird.)
--
ich versuche zu helfen, sorry wenn ich nen scheiß rede ^^
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
30.11.2006, 10:28 Uhr
J-jayz-Z
Perl Crack ala Carte
(Operator)


Geht bei mir einwandfrei (auch ohne this->

C++:
#include <iostream>

class First
{
public:
    First() { }
    void out()
    {
        std::cout << "Ich bin a" << std::endl;
    }

    void bla()
    {
        std::cout << "überall..." << std::endl;
    }
};

class Second
{
private:
    First* foo;
public:
    Second() {
        this->foo = new First();
        std::cout << "Objekt erzeugt .." << std::endl;
        foo->out();
    }
    void out()
    {
        std::cout << "Ich bin b" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    Second second;
    std::cin.get();
    return EXIT_SUCCESS;
}


Nur die Sache mit Pointern auf die Basisklasse ... Das funtzt bei mir nicht. Ich sehe genau wie in meinem obigen Beispiel immer nur die Methoden der Basisklasse, wenn ich ein Objekt der Unterklasse reinpacke. Hast du evtl. ein Beispiel, wie du es meinst, virtual ?

EDIT: Im Destruktor natürlich dann noch das Objekt mit delete löschen.
--
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="66756e2d736f66742e6465"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

Dieser Post wurde am 30.11.2006 um 10:29 Uhr von J-jayz-Z editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
30.11.2006, 10:45 Uhr
Th



Du mußt die Methode "out" (in der Basisklasse) als virtual deklarieren, dann klappt es auch:

C++:
virtual void out()
{
   std::cout << "Ich bin a" << std::endl;
}

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: