Qual è il metodo preferito per ottenere l'equivalente C++ di instanceof
?equivalente C++ di istanza di
risposta
Provare a utilizzare:
if(NewType* v = dynamic_cast<NewType*>(old)) {
// old was safely casted to NewType
v->doSomething();
}
Ciò richiede il compilatore per avere il supporto RTTI abilitato.
MODIFICA: Ho avuto alcuni buoni commenti su questa risposta!
Ogni volta che è necessario utilizzare un dynamic_cast (o instanceof) è meglio chiedersi se è una cosa necessaria. In genere è un segno di design scadente.
soluzioni tipiche sta mettendo il comportamento speciale per la classe che si sta verificando per in una funzione virtuale nella classe base, o forse l'introduzione di qualcosa di simile a un visitor in cui è possibile introdurre comportamenti specifici per le sottoclassi senza cambiare l'interfaccia (tranne che per l'aggiunta del interfaccia di accettazione del visitatore, naturalmente).
Come sottolineato, dynamic_cast non viene fornito gratuitamente. Un hack semplice e coerente che gestisce la maggior parte (ma non tutti i casi) è fondamentalmente l'aggiunta di una enumerazione che rappresenta tutti i possibili tipi che la tua classe può avere e controlla se hai ottenuto quello giusto.
if(old->getType() == BOX) {
Box* box = static_cast<Box*>(old);
// Do something box specific
}
Questo non è un buon design oo, ma può essere una soluzione e il suo costo è più o meno solo una chiamata di funzione virtuale. Funziona anche indipendentemente dal fatto che RTTI sia abilitato o meno.
Si noti che questo approccio non supporta più livelli di ereditarietà, quindi se non stai attento si potrebbe finire con il codice simile a questo:
// 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
}
deve avere almeno un metodo virtuale per farlo funzionare – vava
Questo è generalmente il caso quando si esegue un controllo "instanceof" – Laserallan
Se si usare instanceof, nella maggior parte dei casi c'è qualcosa di sbagliato nel tuo progetto. – mslot
#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);
}
Questo è un pessimo esempio. Perché non usare il sovraccarico, che è più economico? – user1095108
Il problema principale è che non riesce a rispondere alla domanda. 'instanceof' interroga il tipo dinamico, ma in questa risposta il tipo dinamico e statico corrisponde sempre. – MSalters
@HHH la tua risposta è molto lontana dalla domanda che ti viene posta! – programmer
A seconda di cosa si vuole fare voi potrebbe fare questo:
template<typename Base, typename T>
inline bool instanceof(const T*) {
return std::is_base_of<Base, T>::value;
}
Usa:
if (instanceof<BaseClass>(ptr)) { ... }
Tuttavia, questo funziona esclusivamente sui tipi come noto dal compilatore.
Edit:
Questo codice dovrebbe funzionare per i puntatori polimorfici:
template<typename Base, typename T>
inline bool instanceof(const T *ptr) {
return dynamic_cast<const Base*>(ptr) != nullptr;
}
Esempio: http://cpp.sh/6qir
Soluzione elegante e ben fatta. +1 Ma fai attenzione a ottenere il puntatore corretto. Non valido per il puntatore polimorfico? –
Cosa succede se abbiamo deferenziato il puntatore quando si utilizza questa funzione? Potrebbe quindi funzionare per i puntatori polimorfici? –
No, funziona solo sui tipi noti al compilatore. Non funzionerà con i puntatori polimorfici, non importa se si derefernece o no. Aggiungerò qualcosa che potrebbe funzionare in quel caso però. – panzi
questo ha funzionato perfetto per me usando Code :: Blocks IDE con 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;
}
@Andres si prega di leggere la domanda prima di inviare una risposta. – programmer
@programmer Penso che tu intenda chiamare @pgp, ho semplicemente corretto la sua formattazione del codice. Inoltre, la sua risposta sembra essere fondamentalmente "use' typeid' ", che mentre è sbagliato (" Non vi è alcuna garanzia che la stessa istanza di std :: type_info venga chiamata da tutte le valutazioni dell'espressione typeid sullo stesso tipo ... 'assert (typeid (A) == typeid (A));/* not guaranteed * /' ", vedi [cppreference.com] (http://en.cppreference.com/w/cpp/language/typeid#Notes)), indica che ha tentato almeno di rispondere alla domanda, se inutilmente, perché ha trascurato di offrire un esempio di lavoro minimo. –
@Andreas, mi dispiace! il mio male, modificherò il post. – programmer
dynamic_cast
è noto per essere inefficiente. Attraversa la gerarchia dell'ereditarietà e è l' l'unica soluzione se si dispone di più livelli di ereditarietà e occorre verificare se un oggetto è un'istanza di uno qualsiasi dei tipi nella relativa gerarchia di tipi.
Ma se una forma più limitata di instanceof
che controlla solo se un oggetto è esattamente il tipo specificato, è sufficiente per le vostre esigenze, la funzione di sotto sarebbe molto più efficiente:
template<typename T, typename K>
inline bool isType(const K &k) {
return typeid(T).hash_code() == typeid(k).hash_code();
}
Ecco un esempio di come ci si richiama la funzione di cui sopra:
DerivedA k;
Base *p = &k;
cout << boolalpha << isType<DerivedA>(*p) << endl; // true
cout << boolalpha << isType<DerivedB>(*p) << endl; // false
Faresti specificare modello tipo A
(come il tipo che stai controllando per), e passare l'oggetto che si desidera verificare come argomento (da cui tipo di modello K
sarebbe dedotto).
Preferita da chi? – user51568
Preferita per prestazioni e compatibilità ... –
non è giusto chiedere "instanceof - in che lingua?" – mysticcoder