7 Stimmen

Ein Zeiger, zwei verschiedene Klassen in c++

Angenommen, ich habe zwei Strukturen a und b, die jeweils mehrere Variablen enthalten (die meisten Variablen sind C++-Kerntypen, aber nicht alle).

Gibt es eine Möglichkeit, einen Zeiger mit dem Namen c zu erstellen, der auf eine von ihnen zeigen kann? Alternativ, gibt es eine Möglichkeit, eine Menge zu erstellen, die eine von ihnen halten kann?

Danke

5voto

Björn Pollex Punkte 72424

Der übliche Weg, um einen Zeiger zu erstellen, der auf eines der beiden zeigen kann, besteht darin, sie von einer gemeinsamen Basisklasse erben zu lassen. Jeder Zeiger der Basisklasse kann auf eine beliebige Unterklasse zeigen. Beachten Sie, dass Sie auf diese Weise nur auf Elemente zugreifen können, die Teil der Basisklasse sind, über diesen Zeiger:

class Base {
public:
    int a;
};

class Sub1 : public Base {
public:
    int b;
};

class Sub2 : public Base {
public:
    int c;
};

int main() {
    Base* p = new Sub1;
    p->a = 1; // legal
    p->b = 1; // illegal, kann nicht auf Elemente der Unterklasse zugreifen
    p = new Sub2; // kann auf jede Unterklasse zeigen
}

Was Sie erreichen möchten, wird als Polymorphismus bezeichnet und ist eines der grundlegenden Konzepte der objektorientierten Programmierung. Ein Weg, um auf Elemente der Unterklasse zuzugreifen, besteht darin, den Zeiger zu downcasten. Wenn Sie dies tun, müssen Sie sicherstellen, dass Sie ihn auf den korrekten Typ casten:

static_cast(p)->b = 1; // legal, p zeigt tatsächlich auf ein Sub1
static_cast(p)->c = 1; // illegal, p zeigt tatsächlich auf ein Sub1

Was Ihre zweite Frage betrifft, mit der oben beschriebenen Technik können Sie eine Reihe von Zeigern auf eine Basisklasse erstellen, die dann Instanzen einer beliebigen Unterklasse halten können (diese können auch gemischt sein):

std::set base_set;
base_set.insert(new Sub1);
base_set.insert(new Sub2);

4voto

Alternativ gibt es einen Weg, eine Menge zu erstellen, die eins von beiden halten kann?

Schauen Sie sich Boost.Any und Boost.Variant an. Wenn Sie nur 2 Klassen haben, reicht variant aus. Wenn Sie andere Typen planen und dieses 'Set' nicht neu kompilieren möchten, verwenden Sie any.

Verwenden Sie dann einen Container von entweder any oder variant.

#include 
#include 

#include 

class A { };
class B { };
class C { };

int main()
{
    // any

    std::vector anies;
    anies.push_back(A());
    anies.push_back(B());

    A a0 = boost::any_cast(anies[0]);
    A b0 = boost::any_cast(anies[1]); // wirft boost::bad_any_cast

    // variant
    std::vector > vars;
    vars.push_back(A());
    vars.push_back(B());

    A a1 = boost::get(vars[0]);
    A b1 = boost::get(vars[1]); // wirft boost::bad_get

    // und hier ist der Hauptunterschied:
    anies.push_back(C()); // OK
    vars.push_back(C());  // Kompilierfehler
}

Bearbeitung: Es ist natürlich auch möglich, mehr als 2 Klassen für variant zu haben. Aber variant so zu erweitern, dass es einen neuen unerwarteten Typen halten kann, ohne neu kompiliert zu werden, ist es nicht.

3voto

Simone Punkte 11220

Wenn a und b nicht miteinander in Beziehung stehen, können Sie einen void* oder noch besser einen boost any Typ verwenden.

Wenn a eine Oberklasse von b ist, können Sie stattdessen ein a* verwenden.

1voto

Max Punkte 8501

Wenn sie beide von derselben Art erben, können Sie es tun. So funktionieren OOP-Frameworks, indem alle Klassen von Object erben.

0voto

Giorgio Punkte 4775

Definieren Sie einfach eine gemeinsame Superklasse C und zwei Unterklassen A, B von C. Wenn A und B keine gemeinsame Struktur haben (keine gemeinsamen Attribute), können Sie C leer lassen.

Die Definition:

A *a = new A();
B *b = new B();
C *c;

Dann können Sie sowohl

c = a;

als auch

c = b;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X