Проверка типов в C ++ - PullRequest
       38

Проверка типов в C ++

26 голосов
/ 04 января 2011

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

Class Base
{
}

Class Child:Base
{
}

Base childObject = new Child();

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

Спасибо!

Ответы [ 3 ]

55 голосов
/ 04 января 2011

Есть два способа сделать это. Во-первых, вы можете использовать оператор 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 ++. Лично я считаю, что это легче читать и меньше подвержено ошибкам, но во что бы то ни стало идти с тем, что легче для вас.

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

11 голосов
/ 04 января 2011

Хотя ответ 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
2 голосов
/ 04 января 2011

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

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

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

...