Frage

Ich dachte nach dem Vorbild der typeid() verwenden, aber ich weiß nicht, wie zu fragen, ob diese Art eine Unterklasse einer anderen Klasse ist (was, nebenbei gesagt, abstrakt ist)

War es hilfreich?

Lösung

Sie sollten wirklich nicht. Wenn Ihr Programm wissen muss, welche Klasse ein Objekt ist, zeigt an, dass in der Regel einen Konstruktionsfehler. Sehen Sie, wenn Sie das Verhalten bekommen können Sie mit virtuellen Funktionen möchten. Auch weitere Informationen über das, was Sie versuchen würde helfen, zu tun.

Ich gehe davon aus Sie eine Situation wie diese haben:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

Wenn das, was Sie haben, dann versuchen Sie, so etwas zu tun:

class Base
{
  virtual void bar() = 0;
};

class A : public Base
{
  void bar() {/* do X */}
};

class B : public Base
{
  void bar() {/* do Y */}
};

void foo(Base *p)
{
  p->bar();
}

Edit: Da die Debatte über diese Antwort noch nach so vielen Jahren geht weiter, ich dachte, dass ich in einigen Referenzen werfen sollte. Wenn Sie einen Zeiger oder eine Referenz auf eine Basisklasse haben, und Ihr Code muss die abgeleitete Klasse des Objekts kennen, dann verletzt es Liskov Substitutionsprinzip . Uncle Bob diese ein als " Anathema Orientiertes Design Objekt".

Andere Tipps

class Base
{
  public: virtual ~Base() {}
};

class D1: public Base {};

class D2: public Base {};

int main(int argc,char* argv[]);
{
  D1   d1;
  D2   d2;

  Base*  x = (argc > 2)?&d1:&d2;

  if (dynamic_cast<D2*>(x) == nullptr)
  {
    std::cout << "NOT A D2" << std::endl;
  }
  if (dynamic_cast<D1*>(x) == nullptr)
  {
    std::cout << "NOT A D1" << std::endl;
  }
}

Sie können es mit dynamic_cast tun (zumindest für polymorphe Typen).

Eigentlich auf dem zweiten Gedanken - man kann nicht sagen, ob es nämlich eine bestimmte Art mit dynamic_cast ist -. Sie können jedoch sagen, ob es die Art oder eine Unterklasse davon ist

template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
  return dynamic_cast<const DstType*>(src) != nullptr;
}

dynamic_cast kann bestimmen, ob die Art der Zieltyp überall in der Vererbungshierarchie enthält (ja, es ist ein wenig bekanntes Merkmal, dass, wenn B von A und C erbt, kann er eine A* direkt in eine C* drehen). typeid() kann die genaue Art des Objekts bestimmen. Allerdings sollten diese beiden äußerst sparsam eingesetzt werden. Wie bereits erwähnt, sollten Sie immer dynamischer Typ Identifizierung werden vermieden, weil es ein Konstruktionsfehler anzeigt. (Auch, wenn Sie das Objekt kennen, ist sicher der Zieltyp Sie gesenkten mit einem static_cast tun können. Boost-ein polymorphic_downcast bietet, die einen niedergeschlagenen mit dynamic_cast und assert im Debug-Modus zu tun, und im Release-Modus wird es nur verwenden a static_cast).

Ich bin nicht einverstanden, dass Sie sollten nie eine Objekttyp in C ++ überprüfen möchten. Wenn Sie es vermeiden kann, stimme ich zu, dass Sie sollten. Zu sagen, Sie sollten dies nie tun unter keinen Umständen allerdings zu weit geht. Sie können dies in sehr vielen Sprachen tun, und es kann Ihr Leben viel einfacher machen. Howard Pinsley zum Beispiel zeigte uns, wie in seinem Beitrag auf C #.

Ich mache viel Arbeit mit dem Qt-Framework. Im allgemeinen Modell, das ich, was ich tun sie nach der Art und Weise Dinge zu tun (zumindest, wenn sie in ihrem Rahmen arbeiten). Die QObject-Klasse ist die Basisklasse aller Qt-Objekte. Diese Klasse hat die Funktionen isWidgetType () und isWindowType () als eine schnelle Unterklasse überprüfen. Warum also nicht in der Lage sein, Ihre eigenen abgeleiteten Klassen zu überprüfen, was vergleichbar ist es die Natur ist? Hier ist ein QObject Spin-off von einigen dieser anderen Stellen:

class MyQObject : public QObject
{
public:
    MyQObject( QObject *parent = 0 ) : QObject( parent ){}
    ~MyQObject(){}

    static bool isThisType( const QObject *qObj )
    { return ( dynamic_cast<const MyQObject*>(qObj) != NULL ); }
};

Und dann, wenn du um einen Zeiger auf eine QObject sind vorbei, können Sie überprüfen, ob es auf der abgeleiteten Klasse zeigt durch die statische Member-Funktion aufrufen:

if( MyQObject::isThisType( qObjPtr ) ) qDebug() << "This is a MyQObject!";

Ich weiß nicht, ob ich das Problem richtig verstanden hat, so lassen Sie es mich in meinen eigenen Worten neu formulieren ...

Problem: (oder umgekehrt) Da Klassen B und D, festzustellen, ob D eine Unterklasse von B ist

Lösung: Verwenden Sie einige Vorlage Magie! Okay, ernsthaft müssen Sie bei LOKI einen Blick nehmen, eine ausgezeichnete Vorlage Meta-Programmierung Bibliothek, hergestellt von der sagenumwobenen C ++ Autor Andrei Alexandrescu.

Insbesondere herunterladen LOKI und umfassen Kopf TypeManip.h davon im Quellcode verwendet dann die SuperSubclass Klassenvorlage wie folgt:

if(SuperSubClass<B,D>::value)
{
...
}

Nach der Dokumentation wird SuperSubClass<B,D>::value wahr sein, wenn B eine öffentliche Basis von D ist, oder wenn B und D ist Aliase des gleichen Typs.

d. entweder D ist eine Unterklasse von B oder D die gleiche wie B ist.

Ich hoffe, das hilft.

Bearbeiten

Bitte beachten Sie die Auswertung von SuperSubClass<B,D>::value bei der Kompilierung geschieht im Gegensatz zu einigen Methoden, die dynamic_cast verwenden, daher gibt es keine Strafe für die Verwendung dieses Systems zur Laufzeit.

#include <stdio.h>
#include <iostream.h>

class Base
{
  public: virtual ~Base() {}

  template<typename T>
  bool isA() {
    return (dynamic_cast<T*>(this) != NULL);
  }
};

class D1: public Base {};
class D2: public Base {};
class D22: public D2 {};

int main(int argc,char* argv[]);
{
  D1*   d1  = new D1();
  D2*   d2  = new D2();
  D22*  d22 = new D22();

  Base*  x = d22;

  if( x->isA<D22>() )
  {
    std::cout << "IS A D22" << std::endl;
  }
  if( x->isA<D2>() )
  {
    std::cout << "IS A D2" << std::endl;
  }
  if( x->isA<D1>() )
  {
    std::cout << "IS A D1" << std::endl;
  }
  if(x->isA<Base>() )
  {
    std::cout << "IS A Base" << std::endl;
  }
}

Ergebnis:

IS A D22
IS A D2
IS A Base

Sie können es nur bei der Kompilierung-Vorlagen verwenden, es sei denn, Sie RTTI verwenden.

Damit können Sie die typeid Funktion benutzen, die einen Zeiger auf eine type_info Struktur ergeben wird, die Informationen über die Art enthält.

Lesen Sie, es unter Wikipedia

In c # können Sie einfach sagen:

if (myObj is Car) {

}
  

Ich dachte nach dem Vorbild des typeid() mit ...

typeid().name():

Nun ja, könnte es durch einen Vergleich durchgeführt werden. Wenn wir die bereits beschriebene Situation, in:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

Eine mögliche Implementierung von foo(Base *p) sei:

#include <typeinfo>

void foo(Base *p)
{
    if(typeid(*p) == typeid(A))
    {
        // the pointer is pointing to the derived class A
    }  
    else if (typeid(*p).name() == typeid(B).name()) 
    {
        // the pointer is pointing to the derived class B
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top