6 ответов:
попробуйте использовать:
if(NewType* v = dynamic_cast<NewType*>(old)) { // old was safely casted to NewType v->doSomething(); }для этого требуется, чтобы ваш компилятор включил поддержку rtti.
изменить: У меня было несколько хороших комментариев по этому ответу!
каждый раз, когда вам нужно использовать dynamic_cast (или instanceof), вам лучше спросить себя, Является ли это необходимой вещью. Это вообще признак плохого дизайна.
типичные обходные пути помещают специальное поведение для класса, который вы проверяете, в виртуальную функцию в базовом классе или возможно, вводя что-то вроде гость где вы можете ввести определенное поведение для подклассов без изменения интерфейса (за исключением добавления интерфейса приема посетителей, конечно).
как указано dynamic_cast не приходит бесплатно. Простой и последовательно выполняющийся хак, который обрабатывает большинство (но не все случаи), в основном добавляет перечисление, представляющее все возможные типы, которые может иметь ваш класс, и проверяет, правильно ли вы его получили.
if(old->getType() == BOX) { Box* box = static_cast<Box*>(old); // Do something box specific }Это не очень хороший дизайн oo, но это может быть обходной путь, и его стоимость более или менее является только виртуальным вызовом функции. Он также работает независимо от того, включен RTTI или нет.
обратите внимание, что этот подход не поддерживает несколько уровней наследования, поэтому, если вы не будете осторожны, вы можете закончить код, выглядящий так:
// Here we have a SpecialBox class that inherits Box, since it has its own type // we must check for both BOX or SPECIAL_BOX if(old->getType() == BOX || old->getType() == SPECIAL_BOX) { Box* box = static_cast<Box*>(old); // Do something box specific }
В зависимости от того, что вы хотите сделать, вы можете сделать это:
template<typename Base, typename T> inline bool instanceof(const T*) { return std::is_base_of<Base, T>::value; }использование:
if (instanceof<BaseClass>(ptr)) { ... }однако это чисто работает на типах, известных компилятором.
Edit:
этот код должен работать для полиморфные указатели:
template<typename Base, typename T> inline bool instanceof(const T *ptr) { return dynamic_cast<const Base*>(ptr) != nullptr; }пример:http://cpp.sh/6qir
dynamic_castКак известно, неэффективно. Он проходит вверх по иерархии наследования, и это единственное решение, если у вас есть несколько уровней наследования, и нужно проверить, является ли объект экземпляром любого из типов в его иерархии типов.но если более ограниченная форма
instanceofэто только проверяет, является ли объект именно тем типом, который вы указываете, достаточно для ваших нужд, функция ниже будет намного эффективнее:template<typename T, typename K> inline bool isType(const K &k) { return typeid(T).hash_code() == typeid(k).hash_code(); }здесь пример того, как вы вызываете функцию выше:
DerivedA k; Base *p = &k; cout << boolalpha << isType<DerivedA>(*p) << endl; // true cout << boolalpha << isType<DerivedB>(*p) << endl; // falseвы бы указали тип шаблона
A(как тип, который вы проверяете), и передать объект, который вы хотите проверить в качестве аргумента (из которого тип шаблонаKбудет выведено).
реализация Instanceof без dynamic_cast
я думаю, что этот вопрос все еще актуален сегодня. Используя стандарт C++11, вы теперь можете реализовать
#include <iostream.h> #include<typeinfo.h> template<class T> void fun(T a) { if(typeid(T) == typeid(int)) { //Do something cout<<"int"; } else if(typeid(T) == typeid(float)) { //Do Something else cout<<"float"; } } void main() { fun(23); fun(90.67f); }
это работало идеально для меня, используя Code:: Blocks IDE с GCC complier
#include<iostream> #include<typeinfo> #include<iomanip> #define SIZE 20 using namespace std; class Publication { protected: char title[SIZE]; int price; public: Publication() { cout<<endl<<" Enter title of media : "; cin>>title; cout<<endl<<" Enter price of media : "; cin>>price; } virtual void show()=0; }; class Book : public Publication { int pages; public: Book() { cout<<endl<<" Enter number of pages : "; cin>>pages; } void show() { cout<<endl<<setw(12)<<left<<" Book Title"<<": "<<title; cout<<endl<<setw(12)<<left<<" Price"<<": "<<price; cout<<endl<<setw(12)<<left<<" Pages"<<": "<<pages; cout<<endl<<" ----------------------------------------"; } }; class Tape : public Publication { int duration; public: Tape() { cout<<endl<<" Enter duration in minute : "; cin>>duration; } void show() { cout<<endl<<setw(10)<<left<<" Tape Title"<<": "<<title; cout<<endl<<setw(10)<<left<<" Price"<<": "<<price; cout<<endl<<setw(10)<<left<<" Duration"<<": "<<duration<<" minutes"; cout<<endl<<" ----------------------------------------"; } }; int main() { int n, i, type; cout<<endl<<" Enter number of media : "; cin>>n; Publication **p = new Publication*[n]; cout<<endl<<" Enter "<<n<<" media details : "; for(i=0;i<n;i++) { cout<<endl<<" Select Media Type [ 1 - Book / 2 - Tape ] "; cin>>type; if ( type == 1 ) { p[i] = new Book(); } else if ( type == 2 ) { p[i] = new Tape(); } else { i--; cout<<endl<<" Invalid type. You have to Re-enter choice"; } } for(i=0;i<n;i++) { if ( typeid(Book) == typeid(*p[i]) ) { p[i]->show(); } } return 0; }
Comments