tipos simple multiple metodo llamar herencia ejercicios ejemplos como clases clase c++ class subclass identification

simple - ¿Cómo puedo verificar si el tipo de un objeto es una subclase particular en C++?



super en java (10)

Estaba pensando en el uso de typeid() ...

Bueno, sí, podría hacerse comparando: typeid().name() . Si tomamos la situación ya descrita, donde:

class Base; class A : public Base {...}; class B : public Base {...}; void foo(Base *p) { if(/* p is A */) /* do X */ else /* do Y */ }

Una posible implementación de foo(Base *p) sería:

#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 } }

Estaba pensando en el uso de typeid() pero no sé cómo preguntar si ese tipo es una subclase de otra clase (que, por cierto, es abstracta)


En c # puedes simplemente decir:

if (myObj is Car) { }


No estoy de acuerdo con que nunca desee verificar el tipo de un objeto en C ++. Si puedes evitarlo, acepto que deberías. Sin embargo, decir que NUNCA debes hacer esto bajo ninguna circunstancia es ir demasiado lejos. Puede hacerlo en muchos idiomas y puede hacer que su vida sea mucho más fácil. Howard Pinsley, por ejemplo, nos mostró cómo en su publicación en C #.

Hago mucho trabajo con el Marco de Qt. En general, soy un modelo de lo que hago después de la forma en que hacen las cosas (al menos cuando trabajan en su marco). La clase QObject es la clase base de todos los objetos Qt. Esa clase tiene las funciones isWidgetType () e isWindowType () como una prueba de subclase rápida. Entonces, ¿por qué no puedes verificar tus propias clases derivadas, que es comparable en su naturaleza? Aquí hay un spin off de QObject de algunas de estas otras publicaciones:

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 ); } };

Y luego, cuando está pasando un puntero a un QObject, puede verificar si apunta a su clase derivada llamando a la función miembro estática:

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


No sé si entiendo tu problema correctamente, así que déjame repetirlo en mis propias palabras ...

Problema: dadas las clases B y D , determina si D es una subclase de B (¿o viceversa?)

Solución: ¡Usa algo de magia de plantilla! Bien, en serio, debes echarle un vistazo a LOKI, una excelente biblioteca de metaprogramación de plantillas producida por el legendario autor de C ++ Andrei Alexandrescu.

Más específicamente, descargue LOKI e incluya el encabezado TypeManip.h en su código fuente y luego use la plantilla de clase SuperSubclass siguiente manera:

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

Según la documentación, SuperSubClass<B,D>::value será verdadero si B es una base pública de D , o si B y D son alias del mismo tipo.

es decir, o D es una subclase de B o D es lo mismo que B

Espero que esto ayude.

editar:

Tenga en cuenta que la evaluación de SuperSubClass<B,D>::value ocurre en el momento de la compilación a diferencia de algunos métodos que usan dynamic_cast , por lo tanto, no hay penalización por usar este sistema en tiempo de ejecución.


Puedes hacerlo con dynamic_cast (al menos para tipos polimórficos).

En realidad, pensándolo bien, no se puede decir si es ESPECÍFICAMENTE un tipo particular con dynamic_cast pero se puede decir si es ese tipo o cualquier subclase del mismo.

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


Realmente no deberías. Si su programa necesita saber qué clase es un objeto, eso generalmente indica un defecto de diseño. Vea si puede obtener el comportamiento que desea utilizando funciones virtuales. Además, más información sobre lo que está tratando de hacer ayudaría.

Supongo que tienes una situación como esta:

class Base; class A : public Base {...}; class B : public Base {...}; void foo(Base *p) { if(/* p is A */) /* do X */ else /* do Y */ }

Si esto es lo que tienes, intenta hacer algo como esto:

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(); }

Editar: Dado que el debate sobre esta respuesta aún continúa después de tantos años, pensé que debería incluir algunas referencias. Si tiene un puntero o referencia a una clase base, y su código necesita conocer la clase derivada del objeto, viola el principio de sustitución de Liskov . El tío Bob llama a esto un " anatema para el diseño orientado a objetos ".


Solo puede hacerlo en tiempo de compilación utilizando plantillas, a menos que use RTTI.

Le permite usar la función typeid que dará un puntero a una estructura type_info que contiene información sobre el tipo.

Lea sobre esto en Wikipedia


dynamic_cast puede determinar si el tipo contiene el tipo de destino en cualquier lugar de la jerarquía de herencia (sí, es una característica poco conocida que si B hereda de A y C , puede convertir un A* directamente en un C* ). typeid() puede determinar el tipo exacto del objeto. Sin embargo, ambos deben usarse con moderación. Como ya se ha mencionado, siempre debe evitar la identificación de tipo dinámico, ya que indica un defecto de diseño. (Además, si sabes que el objeto está seguro del tipo de objetivo, puedes hacer un static_cast con un static_cast . Boost ofrece un static_cast polymorphic_downcast que hará un dynamic_cast con dynamic_cast y assert en modo de depuración, y en modo de lanzamiento solo usará un static_cast ).


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; } }


#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; } }

Resultado:

IS A D22 IS A D2 IS A Base