Сбор базовых типов требует поведения в производном типе [дубликат]

Синтаксис:

:%s/<dog\/>/<cat\\>/g
23
задан templatetypedef 23 November 2012 в 21:53
поделиться

3 ответа

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

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

50
ответ дан cameron 18 August 2018 в 17:30
поделиться
  • 1
    Он хочет знать, является ли объект базой, а не если это производный класс. – Puppy 4 January 2011 в 00:16
  • 2
    Ах ... Я смутился его образцовым кодом, который проверял, указывает ли указатель на дочерний тип. Действительная точка. – templatetypedef 4 January 2011 в 00:18

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

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

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

2
ответ дан Puppy 18 August 2018 в 17:30
поделиться
  • 1
    Вам также необходимо убедиться, что вы скомпилируете с включенной идентификацией типа времени выполнения (RTTI). – Richard Cook 4 January 2011 в 00:08
  • 2
    Обратите внимание, что этот работает только , если сравниваемый элемент имеет vtbl. – Billy ONeal 4 January 2011 в 00:09
  • 3
    @Billy: Это правда, но кто не дает своим базовым классам виртуальные деструкторы? Виртуальные функции - это практически точка наследования. Небезосновательно ожидать этого. – Puppy 4 January 2011 в 00:13
  • 4
    @Richard Cook: Если вы используете компилятор C ++, у него будет поддержка RTTI. Отключение RTTI выключилось бы в неконфигурируемом режиме, и в общем вопросе о C ++ нет реальной причины перечислять функции C ++, которые не следует отключать. – CB Bailey 4 January 2011 в 00:13
  • 5
    @ 7vies: вы не наследуете контейнеры STL. Если ты не сумасшедший. Или так опытный на языке, что вы уже знаете о typeid () и ограничении виртуальной функции. @Charles: Я также редко предоставляю свои классы виртуальным деструкторам, но я всегда это делаю, если планирую унаследовать от них. – Puppy 4 January 2011 в 00:17

Хотя ответ 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
10
ответ дан Tim 18 August 2018 в 17:30
поделиться
  • 1
    Я второй ответ. Ответ DeadMG, хотя правильный, не может быть хорошей практикой программирования ..! – Jay D 4 January 2011 в 00:39
  • 2
    Это хорошо работает, когда вы хотите сделать что-то внутреннее для объекта. С другой стороны, когда вы хотите обрабатывать объекты в зависимости от их типов, это становится сложным и неудобным (со всеми этими двойными диспетчерами и посетителями) – Roman L 4 January 2011 в 00:43
  • 3
    @ 7vies, правда, но чаще всего этот метод виртуального метода будет работать лучше всего и будет проще всего поддерживать. Бывают случаи, когда dynamic_cast или typeid - правильный подход, но это реже. – Tim 4 January 2011 в 00:53
  • 4
    Спасибо за ответ, но, как я уже сказал, это не мой код, и я просто быстро решу проблему, ничего не меняя. – Homam 4 January 2011 в 01:35
  • 5
    @Homam, вы все равно можете сделать это с помощью OO, создав свои собственные классы-оболочки. Но обычно это не стоит того, и typeid / dynamic_cast становится более разумным вариантом. Особенно, если вы просто ищете быстрое решение. – Tim 4 January 2011 в 01:54
Другие вопросы по тегам:

Похожие вопросы: