Что является эквивалентом C ++ 11 для Java instanceof

Я хочу знать, что современный C ++ 11 эквивалент Java в instanceof. Я видел это ТАК сообщение но он довольно старый и ему было интересно, есть ли более современное и лучшее решение в C ++ 11?

Я надеялся, что есть возможность использовать конструкцию switch, не прибегая к ручному классу enum.

class A {

};

class B : public A {

}

class C : public A {

}

on_event(A& obj)
{
switch (obj) {
case A:
case B:
case C:
}
}

Мой базовый класс не имеет никаких виртуальных методов или функций. Я представляю дерево выражений для парсера, а базовый класс — это просто полиморфный держатель — как ADT в Haskell / OCaml.

8

Решение

Тот же ответ все еще применяется, и всегда был таким в C ++:

if (C * p = dynamic_cast<C *>(&obj))
{
// The type of obj is or is derived from C
}
else
{
// obj is not a C
}

Эта конструкция требует A быть полиморфным, то есть иметь виртуальные функции-члены.

Также обратите внимание, что это поведение отличается от сравнения typeid(obj) == typeid(C), поскольку последний проверяет точную идентичность типа, тогда как динамическое приведение, а также Java instanceofтолько для проверки, чтобы целевой тип был базовым классом типа самого производного объекта.

12

Другие решения

В C ++ простые старые данные (POD) не имеют информации о типе времени выполнения. Все описанные классы занимают ровно 1 байт и имеют идентичные представления времени выполнения в любом компиляторе с пустой оптимизацией базового класса.

Таким образом, то, что вы хотите, не может быть сделано.

Добавление виртуального деструктора в базовый класс добавляет в RTTI и dynamic_cast служба поддержки.

Добавление enum или же int поле к базе, которое инициализируется по-разному для каждого производного класса, также работает.

Еще один вариант — создать шаблонную функцию и сохранить указатель на нее, например, так:

using my_type_id=void(*)();
template<class>void get_my_type_id_helper(){};
template<class T> my_type_id get_my_type_id(){return get_my_type_id_helper<T>;}

а затем хранить my_type_id в A инициализируется соответствующим образом. Это переизобретает RTTI, и, если вам нужно больше возможностей, вы будете использовать C ++ RTTI.

В C ++ вы платите только за то, что просите: вы можете попросить классы без RTTI, которые вы сделали, и получить это.

RTTI — это информация о типе времени выполнения. POD — это простые старые данные, термин C ++ 03. Многие классы не являются POD: проще всего добавить virtual деструктор. C ++ 11 имеет более мелкозернистую стандартную компоновку и совокупные термины.

Технически RTTI и POD не являются противоположностями друг другу: существуют классы без RTTI, которые не являются POD.

Обратите внимание, что MSVC имеет опции не генерировать RTTI, и его агрессивное сворачивание Comdat может нарушить ручной RTTI, который я делал выше, в обоих случаях в нарушение стандарта.

0

Может быть, вы заинтересованы в ответе, который я разместил в упомянутом вами старом посте SO.

https://stackoverflow.com/a/49296405/1266588

Ответ представляет собой реализацию instanceof без использования dynamic_cast основанный на C ++ 11, метапрограммирование шаблона а также RTTI. Небольшое приложение для измерения производительности демонстрирует, что оно более эффективно, чем dynamic_cast если вы используете оптимизацию компилятора.

0

Не делай этого. В большинстве случаев вы должны пересмотреть свой дизайн, когда вы просите instanceof или же dynamic_cast,

Зачем? Вы, скорее всего, нарушаете Принцип подстановки Лискова.

Как насчет этого подхода:

class A {
public:
virtual void action();
virtual ~A();
};

class B : public A {
public: void action() override;
};

class C : public A {
public: void action() override;
};

void on_event(A& obj)
{
obj.action();
}

Обратите внимание, что, как указал @Yakk, вам нужен хотя бы один virtual метод в любом случае, чтобы получить динамический полиморфизм. И есть правило, которое гласит: если у вас есть хотя бы один виртуальный метод, всегда также пишите виртуальный деструктор в базовом классе.

Вы можете сделать все это с помощью шаблонов и специализаций или маркировки типов, но я беру из вашего вопроса — пришедшего с Java — вы пока не хотите туда идти. Вы действительно лайк виртуальные методы, не так ли? Извините, что вы должны пометить их в C ++.

-1

Если вы хотите ограничить себя типами, известными во время компиляции (вместо того, чтобы работать через указатели на экземплярах классов с vtables) — тогда C ++ 11 и более поздние версии имеют instanceof эквивалент: это станд :: is_base_of.

Вы также можете проверить станд :: шаблона is_convertible а также станд :: is_same.

-1
По вопросам рекламы [email protected]