Поиск типа объекта в C ++

У меня есть class A и другой class, который наследует от него, B. Я переопределяю функцию, которая принимает объект типа A в качестве параметра, поэтому мне нужно принять A. Однако, я позже вызываю функции, которые имеют только B, поэтому я хочу вернуть false и не продолжать, если переданный объект не относится к типу B.

Каков наилучший способ узнать, какой тип объекта передал моей функции?

dynamic_cast должен делать трюк

TYPE& dynamic_cast (object); TYPE* dynamic_cast (object); 

Ключевое слово dynamic_cast выдает привязку из одного указателя или ссылочного типа в другой, выполняя проверку времени выполнения, чтобы гарантировать достоверность приведения.

Если вы попытаетесь наложить указатель на тип, который не является типом фактического объекта, результат приведения будет NULL. Если вы попытаетесь применить для ссылки на тип, который не является типом фактического объекта, бросок будет генерировать исключение bad_cast .

Убедитесь, что в classе Base есть по крайней мере одна виртуальная функция, чтобы сделать работу dynamic_cast.

Динамический листинг является лучшим для описания проблемы, но я просто хочу добавить, что вы можете найти тип classа с помощью:

 #include  ... string s = typeid(YourClass).name() 

Это называется RTTI, но вы почти наверняка хотите пересмотреть свой дизайн здесь, потому что поиск типа и выполнение специальных вещей на основе этого делает ваш код более хрупким.

Вероятно, вставляйте в свои объекты идентификационный «тег» и используйте его для различения объектов classа A и объектов classа B.

Это, однако, показывает недостаток в дизайне. В идеале те методы из B, которые A не имеют, должны быть частью A, но оставлены пустыми, а B их перезаписывает. Это устраняет код, специфичный для classа, и более соответствует духу ООП.

Вы ищете dynamic_cast(pointer) ?

Чтобы быть полным, я построю сборку Robocide и отметьте, что typeid можно использовать самостоятельно, не используя имя ():

 #include  #include  using namespace std; class A { public: virtual ~A() = default; // We're not polymorphic unless we // have a virtual function. }; class B : public A { } ; class C : public A { } ; int main(int argc, char* argv[]) { B b; A& a = b; cout << "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl; cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl; cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl; cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl; cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl; } 

Вывод:

 a is B: true a is C: false b is B: true b is A: false b is C: false 

Как показали другие, вы можете использовать dynamic_cast. Но, как правило, использование dynamic_cast для определения типа производного classа, над которым вы работаете, указывает на плохой дизайн. Если вы переопределяете функцию, которая принимает указатель на A в качестве параметра, то она должна иметь возможность работать с методами / данными самого classа A и не должна зависеть от данных classа B. В вашем случае вместо переопределения, если вы что метод, который вы пишете, будет работать только с classом B, тогда вы должны написать новый метод в classе B.

Потому что ваш class не является полиморфным. Пытаться:

 struct BaseClas { int base; virtual ~BaseClas(){} }; class Derived1 : public BaseClas { int derived1; }; 

Теперь BaseClas является полиморфным. Я изменил class на struct, потому что члены структуры являются общедоступными по умолчанию.

Ваше описание немного запутанно.

Вообще говоря, хотя некоторые реализации C ++ имеют механизмы для этого, вы не должны спрашивать о типе. Вместо этого вы должны сделать dynamic_cast на указателе на A. Что это будет делать, так это то, что во время выполнения будет проверено фактическое содержимое указателя на A. Если у вас есть B, вы получите указатель на B. В противном случае вы получите исключение или null.

Используйте перегруженные функции. Не требует поддержки dynamic_cast или даже RTTI:

 class A {}; class B : public A {}; class Foo { public: void Bar(A& a) { // do something } void Bar(B& b) { Bar(static_cast(b)); // do B specific stuff } }; 

Если вы можете получить доступ к библиотеке boost, возможно, функция type_id_with_cvr () – это то, что вам нужно, которое может предоставлять тип данных без удаления константных, изменчивых, & и && модификаторов . Вот простой пример в C ++ 11:

 #include  #include  int a; int& ff() { return a; } int main() { ff() = 10; using boost::typeindex::type_id_with_cvr; std::cout << type_id_with_cvr().pretty_name() << std::endl; std::cout << type_id_with_cvr().pretty_name() << std::endl; std::cout << typeid(ff()).name() << std::endl; } 

Надеюсь, это полезно.

  • Есть ли способ отключить перегрузку функций в Postgres
  • Тип возврата '?:' (Тернарный условный оператор)
  • Тип аргумента для сигнала и слота Qt, имеет ли значение задание отступников?
  • Как определить разные типы для одного и того же classа в C ++
  • Где в памяти мои переменные, хранящиеся в C?
  • make arrayList.toArray () возвращает более конкретные типы
  • Условный оператор не может действовать неявно?
  • Типы данных PostgreSQL и C #
  • unsigned short в java
  • JAXB: Как изменить имена classов, сгенерированных XJC, когда тип attr указан в XSD?
  • Как разрешить «должен быть экземпляр строки, строка, заданная» до PHP 7?
  • Давайте будем гением компьютера.