2011-01-03 4 views
23

В C++ я хочу знать, является ли фактический тип объекта одним и тем же классом, а не тем же классом или производным. Это похоже на следующий код C#:Проверка типов в C++

Class Base 
{ 
} 

Class Child:Base 
{ 
} 

Base childObject = new Child(); 

If (childObject.GetType() == typeof(Child)) 
{ 
// do some code 
} 

Спасибо!

+0

Каков тип 'childObject'? В C++ нет общего способа сделать это, потому что во время выполнения понятие типа не существует. –

+0

Хорошо, я отредактирую вопрос – Homam

+2

Хотя вы ничего не сказали о том, что такое childObject.GetType(), тем не менее этот код ужасен, потому что он разворачивается по типу сравнения. Это то, что ООП должно устранить. –

ответ

48

Есть два способа, которыми вы можете это сделать. Во-первых, вы можете использовать оператор typeid, который возвращает структуру type_info, содержащую информацию о типе объекта. Например:

Base* ptr = /* ... */ 
if (typeid(*ptr) == typeid(DerivedType)) { 
    /* ... ptr points to a DerivedType ... */ 
} 

Обратите внимание, что вы должны использовать typeid(*ptr) и не typeid(ptr) здесь. Если вы используете typeid(ptr), вы вернете объект type_info для Base*, так как указатель имеет тип Base*, независимо от того, на что он указывает.

Важно отметить, что это будет проверять, что ptr точек на это точно в DerivedType. Если ptr указывает на объект типа, производный от DerivedType (возможно, EvenMoreDerivedType), этот код будет работать неправильно.

Альтернативный способ проверки того, указываете ли вы на объект некоторого типа, который является более надежным, заключается в использовании оператора dynamic_cast. dynamic_cast выполняет проверенный тип при выполнении во время выполнения, который даст допустимый указатель, если листинг преуспеет, а NULL - в противном случае. Например:

Base* ptr = /* ... */; 
DerivedType* derived = dynamic_cast<DerivedType*>(ptr); 
if (derived) { 
    /* ... points to a DerivedType ... */ 
} 

Это имеет дополнительное преимущество, что если ptr указывает на что-то вроде EvenMoreDerivedType, актеры все равно добиться успеха, потому что EvenMoreDerivedType наследует от DerivedType.

В качестве последней мысли, вы иногда видите код, как это:

Base* ptr = /* ... */ 
if (DerivedType* derived = dynamic_cast<DerivedType*>(ptr)) { 
    /* ... points to a DerivedType ... */ 
} 

Это локально-привязывает derived указатель на тело if заявления и использует тот факт, что отличные от нуля значения оценки для true в C++. Я лично считаю, что это легче читать и менее подвержено ошибкам, но, во что бы то ни стало, подходит для вас, что проще для вас.

Надеюсь, это поможет!

+0

Он хочет знать, является ли объект базой, а не если это производный класс. – Puppy

+0

А ... Я смутился его образцовым кодом, который проверял, указывает ли указатель на дочерний тип. Действительная точка. – templatetypedef

2

Вы можете использовать typeid().

if (typeid(childObject) == typeid(ChildType)) { 
} 

Если это возвращает true, то вы знаете, что это класс ребенка.

+2

Вам необходимо убедиться, что вы скомпилируете с включенной идентификацией типа времени выполнения (RTTI). –

+3

Обратите внимание, что это ** работает только **, если сравниваемый элемент имеет vtbl. –

+0

@Billy: Это правда, но кто не дает своим базовым классам виртуальные деструкторы? Виртуальные функции - это практически точка наследования. Небезосновательно ожидать этого. – Puppy

9

Хотя ответ DeadMG верен (я много раз использовал typeid), я думал, что выброшу его там для потомства. «Правильный» способ сделать это, с объектно-ориентированного представления:

Class Base 
{ 
    virtual void something() { 
     // probably a no-op, but maybe some default stuff 
    } 
} 

Class Child : public Base 
{ 
    virtual void something() { 
     // do your child-specific code here 
    } 
} 

Base* childObject = new Child(); 
childObject->something(); // does the right thing 
+0

I второй этот ответ. Ответ DeadMG, хотя правильный, не может быть хорошей практикой программирования ..! –

+0

Это хорошо работает, когда вы хотите сделать что-то внутреннее для объекта. С другой стороны, когда вы хотите обрабатывать объекты в зависимости от их типов, он становится сложным и неудобным (со всеми этими двойными отправлениями и посетителями) –

+0

@ 7vies, true, но чаще всего этот метод виртуального метода будет работать лучше всего и будет легче всего поддерживать. Бывают случаи, когда dynamic_cast или typeid - правильный подход, но это реже. – Tim

Смежные вопросы