Перейти к содержимому

Как узнать тип объекта c

  • автор:

Узнать реальный тип объекта

Предположим, есть тип базовый класс SceneObject и есть производные от него классы. Я хочу хранить массив объектов этого класса, для этого завожу vector < SceneObject*>obj. Добавляю туда некоторые объекты производных классов. А когда достаю их оттуда, я хочу узнать их реальный тип. typeid(obj[i]).name() всегда выдает тип SceneObject*. Как узнать реальный тип объекта?( Или может быть, я все делаю неправильно. Как тогда сделать массив объектов, производных от одного класса, чтобы потом можно было определить какой это объект?

Отслеживать
задан 15 мая 2016 в 9:56
195 1 1 серебряный знак 9 9 бронзовых знаков

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

Информация о типе — это дополнительная информация. Когда у вас есть виртуальные функции — есть и их таблица, которая по сути и есть информацией о конкретном типе.

Без этого надо хранить информацию о типе где-то отдельно.

Но как вы хотите использовать эту информацию? Для чего? Обычно — без виртуальных функций — она попросту бессмысленна.

Кстати, раз уж вы пользуетесь указателями и иерархией классов — то учтите, что с точки зрения безопасности деструктор базового класса должен быть объявлен как виртуальный!

Отслеживать
ответ дан 15 мая 2016 в 10:13
219k 15 15 золотых знаков 119 119 серебряных знаков 230 230 бронзовых знаков

Для определения реального типа объекта вы можете воспользоваться dynamic_cast : TYPE* dynamic_cast (object);

Отслеживать
ответ дан 15 мая 2016 в 10:00
Мстислав Павлов Мстислав Павлов
6,767 2 2 золотых знака 18 18 серебряных знаков 40 40 бронзовых знаков

Для классов, не содержащих виртуальные функции, это не работает( Может быть, можно как-то по-другому?

15 мая 2016 в 10:07
а тут разве не нужно знать к чему кастовать? а вопросе вроде обратный вопрос?
15 мая 2016 в 10:08

Да, тут нужно знать( Но можно сделать иерархию if-else и попробовать поприводить ко всему, при некотором желании(хотя это медленно и неоптимально)

15 мая 2016 в 10:11

Очевидно, что Вы неправильно выводите имя, должно быть так: typeid(*obj[i]).name() , но это будет работать лишь в том случае, когда SceneObject является полиморфным, т.е. содержит хотя бы одну виртуальную функцию. Это требуется потому, что без этого RTTI по классу отсутствует, и оператору typeid просто неоткуда узнать, что же за тип ему реально передан.

Если Вы немного подумаете, то поймёте, что для того, чтобы получить информацию во время исполнения, нужно использовать какие-то средства времени исполнения. В C++ все эти вещи связаны с виртуальностью и ничем другим. Поэтому без полиморфного базового класса, боюсь, Вам задачу не решить.

Что касается правильно/не правильно. Обычно, если появляется задача узнать реальный тип данных, то это на 99% ошибка дизайна. Реальный тип практически никогда знать не нужно, для выполнения конкретной реализации существует полиморфное поведение, то есть виртуальные функции.

Как узнать тип объекта c

Допустим есть объект a, какого то типа. Вот этот тип нам и нужно определить, например для создания другого объекта такого же типа. Это звучит конечно немного глупо, так как мы всегда знаем какого типа объект, ну а все таки, например в таком контесте:

. // тут очень много кода, например чужого. . // и у нас есть объект x. // А тут нам нужно создать копию объекта x. tpye(x) a(x); // Например, type это такой волшебный преобразователь. . 

Есть способ вот такой:

templateclass T> void Create(T &x)

Но этот тип T никак не могу вынести за пределы этой функции.

Может я чего то не знаю в современном C++?

Re: как определить тип объекта?

От: LaFlour blog: http://spaces.live.com/laflour
Дата: 26.12.02 06:58
Оценка:

Здравствуйте, comer, Вы писали:

C>Допустим есть объект a, какого то типа. Вот этот тип нам и нужно определить, например для создания другого объекта такого же типа. Это звучит конечно немного глупо, так как мы всегда знаем какого типа объект, ну а все таки, например в таком контесте:

Не пробывал задавать новый тип по полученному
но typeid позволяет определить тип

C>

 int i; cout typeid(i).name; //вывыдет int C>

или может я чтото непонял?

:: Into my SONY MDR-R10 sound «DJ Groove — Ноктюрн» ::
Re: как определить тип объекта?

От: Dima2
Дата: 26.12.02 07:41
Оценка: 8 (1)

Вот смотри здесь немного

Автор: DarkGray
Дата: 12.04.02
Автор: DarkGray
Дата: 14.04.02
Re: как определить тип объекта?

От: jazzer Skype: enerjazzer
Дата: 26.12.02 08:07
Оценка: 4 (1)

Здравствуйте, comer, Вы писали:

C>Допустим есть объект a, какого то типа. Вот этот тип нам и нужно определить, например для создания другого объекта такого же типа. Это звучит конечно немного глупо, так как мы всегда знаем какого типа объект, ну а все таки, например в таком контесте:

C>

C>. // тут очень много кода, например чужого. C>. // и у нас есть объект x. C> // А тут нам нужно создать копию объекта x. C>tpye(x) a(x); // Например, type это такой волшебный преобразователь. C>. C>

см. ниже.

C>Есть способ вот такой:

C>

C>templateclass T> void Create(T &x) < T a(x); >C>

C>Но этот тип T никак не могу вынести за пределы этой функции.

Это невозможно, ибо вызов функции — это выражение, а оно по грамматике не может стоять на месте типа в объявлении.

C>Может я чего то не знаю в современном C++? .

Такого способа, к сожалению, нет, но, возможно, он появится, по крайней мере, Строуструп за это ратует (и я лично это очень поддерживаю), можете посмотреть на ео страничке.

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got If you always do what you always did

Re: как определить тип объекта?

От: orangy http://twitter.com/orangy
Дата: 26.12.02 11:48
Оценка:

Здравствуйте, comer, Вы писали:

C>Допустим есть объект a, какого то типа. Вот этот тип нам и нужно определить, например для создания другого объекта такого же типа.
Лучше используй парадигму создание-по-прототипу.

class IPrototype < public: virtual IPrototype *Create() = 0; >; class A : public IPrototype < public: A(int b) < . >virtual IPrototype *Create() < return new A(10); > >;

«Develop with pleasure!»
Re[2]: как определить тип объекта?

От: comer http://getboost.codeplex.com/
Дата: 26.12.02 12:15
Оценка:

Здравствуйте, Dima2, Вы писали:

D>http://www.rsdn.ru/Forum/Message.aspx?mid=44873
Автор: DarkGray
Дата: 12.04.02

Да, спасибо, вот здесь как раз и нашел ответ Павла Кузнецова, что в GCC есть __typeof. Мне как раз для GCC. Пока подобной вещи нет в стандарте. Сегодня попробую.

Re[2]: как определить тип объекта?

От: comer http://getboost.codeplex.com/
Дата: 26.12.02 12:18
Оценка:

Здравствуйте, jazzer, Вы писали:

J>Такого способа, к сожалению, нет, но, возможно, он появится, по крайней мере, Строуструп за это ратует (и я лично
это очень поддерживаю), можете посмотреть на ео страничке.

Я тоже двумя руками за! На этапе компиляции всегда должны быть способы узнать об объекте, типе, функции, все то, что знает о нем компилятор, или почти все . А то не честно как то, компилятор знает, а пользователю — болт. Извините за эмоции.

Re: как определить тип объекта?

От: Кодт
Дата: 26.12.02 13:10
Оценка:

Здравствуйте, comer, Вы писали:

C>Может я чего то не знаю в современном C++?

Посмотри в сторону Александреску и его библиотеки Loki, и его же книги (www.moderncppdesign.com)
Может, чего полезного подчерпнешь

Перекуём баги на фичи!
Re[2]: как определить тип объекта?

От: comer http://getboost.codeplex.com/
Дата: 26.12.02 13:50
Оценка:

Здравствуйте, Кодт, Вы писали:

К>Посмотри в сторону Александреску и его библиотеки Loki, и его же книги (www.moderncppdesign.com)
К>Может, чего полезного подчерпнешь

Там эмуляция typeof вряд ли есть

Re[3]: как определить тип объекта?

От: Кодт
Дата: 26.12.02 14:07
Оценка:

Здравствуйте, comer, Вы писали:

C>Там эмуляция typeof вряд ли есть
То есть

Но, с другой стороны, — а откуда возникла такая задача?
Может, ее по-другому можно решить? Раскрой тайну.

Александреску как раз показывает, что ловкость рук творит чудеса.

Перекуём баги на фичи!
Re[4]: как определить тип объекта?

От: comer http://getboost.codeplex.com/
Дата: 26.12.02 15:55
Оценка:

Здравствуйте, Кодт, Вы писали:

C>>Там эмуляция typeof вряд ли есть
К>То есть
Без обид, я ведь искал typeof. IMHO, решения нет. Просто в данном случае loki вряд ли поможет.

К>Но, с другой стороны, — а откуда возникла такая задача?
К>Может, ее по-другому можно решить? Раскрой тайну.
Всегда можно решить по другому, я и решаю именно так.
Понятное дело, что тип мы знаем, что где то выше этот объект описан.
Но ты иногда изменял у какого нибудь объекта a тип vector, например на list, или еще на что нибудь подобное?
А потом бегать по все программе, и заменять vector::iterator на list::iterator.

Конечно, можно было бы определить typedef для данного конкретного объекта a, или все алгоритмы работающие с a описывать в виде шаблонных функция. Но если бы был typeof(), можно было бы решать элегантнее.

Так же как и вообще без шаблонов когда то писали, и ничего, пользовались макросами, и т.п.

Object. Get Type Метод

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Возвращает объект Type для текущего экземпляра.

public: Type ^ GetType();
public Type GetType ();
member this.GetType : unit -> Type
Public Function GetType () As Type
Возвращаемое значение

Точный тип текущего экземпляра в среде выполнения.

Примеры

В следующем примере кода показано, что GetType возвращает тип среды выполнения текущего экземпляра.

using namespace System; public ref class MyBaseClass <>; public ref class MyDerivedClass: MyBaseClass<>; int main() < MyBaseClass^ myBase = gcnew MyBaseClass; MyDerivedClass^ myDerived = gcnew MyDerivedClass; Object^ o = myDerived; MyBaseClass^ b = myDerived; Console::WriteLine( "mybase: Type is ", myBase->GetType() ); Console::WriteLine( "myDerived: Type is ", myDerived->GetType() ); Console::WriteLine( "object o = myDerived: Type is ", o->GetType() ); Console::WriteLine( "MyBaseClass b = myDerived: Type is ", b->GetType() ); > /* This code produces the following output. mybase: Type is MyBaseClass myDerived: Type is MyDerivedClass object o = myDerived: Type is MyDerivedClass MyBaseClass b = myDerived: Type is MyDerivedClass */ 
using System; public class MyBaseClass < >public class MyDerivedClass: MyBaseClass < >public class Test < public static void Main() < MyBaseClass myBase = new MyBaseClass(); MyDerivedClass myDerived = new MyDerivedClass(); object o = myDerived; MyBaseClass b = myDerived; Console.WriteLine("mybase: Type is ", myBase.GetType()); Console.WriteLine("myDerived: Type is ", myDerived.GetType()); Console.WriteLine("object o = myDerived: Type is ", o.GetType()); Console.WriteLine("MyBaseClass b = myDerived: Type is ", b.GetType()); > > // The example displays the following output: // mybase: Type is MyBaseClass // myDerived: Type is MyDerivedClass // object o = myDerived: Type is MyDerivedClass // MyBaseClass b = myDerived: Type is MyDerivedClass 
type MyBaseClass() = class end type MyDerivedClass() = inherit MyBaseClass() let myBase = MyBaseClass() let myDerived = MyDerivedClass() let o: obj = myDerived let b: MyBaseClass = myDerived printfn $"mybase: Type is " printfn $"myDerived: Type is " printfn $"object o = myDerived: Type is " printfn $"MyBaseClass b = myDerived: Type is " // The example displays the following output: // mybase: Type is MyBaseClass // myDerived: Type is MyDerivedClass // object o = myDerived: Type is MyDerivedClass // MyBaseClass b = myDerived: Type is MyDerivedClass 
' Define a base and a derived class. Public Class MyBaseClass End Class Public Class MyDerivedClass : Inherits MyBaseClass End Class Public Class Test Public Shared Sub Main() Dim base As New MyBaseClass() Dim derived As New MyDerivedClass() Dim o As Object = derived Dim b As MyBaseClass = derived Console.WriteLine("base.GetType returns ", base.GetType()) Console.WriteLine("derived.GetType returns ", derived.GetType()) Console.WriteLine("Dim o As Object = derived; o.GetType returns ", o.GetType()) Console.WriteLine("Dim b As MyBaseClass = derived; b.Type returns ", b.GetType()) End Sub End Class ' The example displays the following output: ' base.GetType returns MyBaseClass ' derived.GetType returns MyDerivedClass ' Dim o As Object = derived; o.GetType returns MyDerivedClass ' Dim b As MyBaseClass = derived; b.Type returns MyDerivedClass 

Комментарии

Так как System.Object является базовым классом для всех типов в системе GetType типов .NET, метод можно использовать для возврата Type объектов, представляющих все типы .NET. .NET распознает следующие пять категорий типов:

  • Классы, производные от System.Object,
  • Типы значений, производные от System.ValueType.
  • Интерфейсы, производные от System.Object начиная с платформа .NET Framework 2.0.
  • Перечисления, производные от System.Enum.
  • Делегаты, производные от System.MulticastDelegate.

Для двух объектов x , y имеющих одинаковые типы среды выполнения, Object.ReferenceEquals(x.GetType(),y.GetType()) возвращает . true В следующем примере используется GetType метод с методом , ReferenceEquals чтобы определить, относится ли одно числовое значение к тому же типу, что и два других числовых значения.

int n1 = 12; int n2 = 82; long n3 = 12; Console.WriteLine("n1 and n2 are the same type: ", Object.ReferenceEquals(n1.GetType(), n2.GetType())); Console.WriteLine("n1 and n3 are the same type: ", Object.ReferenceEquals(n1.GetType(), n3.GetType())); // The example displays the following output: // n1 and n2 are the same type: True // n1 and n3 are the same type: False 
open System let n1 = 12 let n2 = 82 let n3 = 12L printfn $"n1 and n2 are the same type: " printfn $"n1 and n3 are the same type: " // The example displays the following output: // n1 and n2 are the same type: True // n1 and n3 are the same type: False 
Module Example Public Sub Main() Dim n1 As Integer = 12 Dim n2 As Integer = 82 Dim n3 As Long = 12 Console.WriteLine("n1 and n2 are the same type: ", Object.ReferenceEquals(n1.GetType(), n2.GetType())) Console.WriteLine("n1 and n3 are the same type: ", Object.ReferenceEquals(n1.GetType(), n3.GetType())) End Sub End Module ' The example displays the following output: ' n1 and n2 are the same type: True ' n1 and n3 are the same type: False 

Чтобы определить, является ли объект определенным типом, можно использовать ключевое слово или конструкцию сравнения типов языка. Например, можно использовать конструкцию TypeOf…Is в Visual Basic или ключевое is слово в C#.

Метод GetType наследуется всеми типами, производными от Object. Это означает, что в дополнение к использованию ключевого слова сравнения собственного языка можно использовать GetType метод для определения типа конкретного объекта, как показано в следующем примере.

object[] values = < (int) 12, (long) 10653, (byte) 12, (sbyte) -5, 16.3, "string" >; foreach (var value in values) < Type t = value.GetType(); if (t.Equals(typeof(byte))) Console.WriteLine("is an unsigned byte.", value); else if (t.Equals(typeof(sbyte))) Console.WriteLine(" is a signed byte.", value); else if (t.Equals(typeof(int))) Console.WriteLine(" is a 32-bit integer.", value); else if (t.Equals(typeof(long))) Console.WriteLine(" is a 64-bit integer.", value); else if (t.Equals(typeof(double))) Console.WriteLine(" is a double-precision floating point.", value); else Console.WriteLine("'' is another data type.", value); > // The example displays the following output: // 12 is a 32-bit integer. // 10653 is a 32-bit integer. // 12 is an unsigned byte. // -5 is a signed byte. // 16.3 is a double-precision floating point. // 'string' is another data type. 
let values: obj[] = [| 12; 10653L; 12uy -5y; 16.3; "string" |] for value in values do let t = value.GetType() if t.Equals typeof then printfn $" is an unsigned byte." elif t.Equals typeof then printfn $" is a signed byte." elif t.Equals typeof then printfn $" is a 32-bit integer." elif t.Equals typeof then printfn $" is a 64-bit integer." elif t.Equals typeof then printfn $" is a double-precision floating point." else printfn $"'' is another data type." // The example displays the following output: // 12 is a 32-bit integer. // 10653 is a 32-bit integer. // 12 is an unsigned byte. // -5 is a signed byte. // 16.3 is a double-precision floating point. // 'string' is another data type. 
Module Example Public Sub Main() Dim values() As Object = < 12, CLng(10653), CByte(12), CSbyte(-5), 16.3, "string" >For Each value In values Dim t AS Type = value.GetType() If t.Equals(GetType(Byte)) Console.WriteLine(" is an unsigned byte.", value) ElseIf t.Equals(GetType(SByte)) Console.WriteLine(" is a signed byte.", value) ElseIf t.Equals(GetType(Integer)) Console.WriteLine(" is a 32-bit integer.", value) ElseIf t.Equals(GetType(Long)) Console.WriteLine(" is a 64-bit integer.", value) ElseIf t.Equals(GetType(Double)) Console.WriteLine(" is a double-precision floating point.", value) Else Console.WriteLine("'' is another data type.", value) End If Next End Sub End Module ' The example displays the following output: ' 12 is a 32-bit integer. ' 10653 is a 32-bit integer. ' 12 is an unsigned byte. ' -5 is a signed byte. ' 16.3 is a double-precision floating point. ' 'string' is another data type. 

Объект Type предоставляет метаданные, связанные с классом текущего Objectобъекта .

Оператор typeid

Оператор typeid позволяет определить тип объекта во время выполнения.

Результатом typeid является const type_info& . Значение является ссылкой на type_info объект, представляющий идентификатор типа или тип выражения, в зависимости от того, какая форма typeid используется. Дополнительные сведения см. в разделе type_info класса.

Оператор typeid не работает с управляемыми типами (абстрактными деклараторами или экземплярами). Сведения о получении Type указанного типа см. в разделе typeid.

Оператор typeid выполняет проверка во время выполнения при применении к l-значению типа полиморфного класса, где истинный тип объекта не может быть определен статическими сведениями. К таким случаям относятся следующие.

  • Ссылка на класс
  • Указатель, разыменовывая с помощью *
  • Подстрочный указатель ( [ ] ). (Небезопасно использовать подстрок с указателем на полиморфный тип.)

Если выражение указывает на тип базового класса, но объект фактически является типом, производным от этого базового класса, type_info ссылка на производный класс является результатом. Выражение должно указывать на полиморфный тип (класс с виртуальными функциями). В противном случае результатом является type_info статический класс, на который ссылается выражение. Кроме того, указатель должен быть разоменовывлен таким образом, чтобы используемый объект указывал на него. Без разыменовки указателя результатом будет type_info указатель, а не то, что он указывает. Например:

// expre_typeid_Operator.cpp // compile with: /GR /EHsc #include #include class Base < public: virtual void vvfunc() <>>; class Derived : public Base <>; using namespace std; int main() < Derived* pd = new Derived; Base* pb = pd; cout 

Если выражение расшифровывает указатель и значение указателя равно нулю, typeid вызывает исключение bad_typeid. Если указатель не указывает на допустимый объект, __non_rtti_object создается исключение. Он указывает на попытку проанализировать RTTI, которая вызвала ошибку, так как объект каким-то образом недопустим. (Например, это плохой указатель или код не компилировался с помощью /GR.

Если выражение не является указателем, а не ссылкой на базовый класс объекта, результатом является type_info ссылка, представляющая статический тип выражения. Статический тип выражения относится к типу выражения, известному во время компиляции. Семантика исполнения игнорируется при оценке статического типа выражения. Кроме того, ссылки по возможности игнорируются при определении статического типа выражения:

// expre_typeid_Operator_2.cpp #include int main() < typeid(int) == typeid(int&); // evaluates to true >

typeid также можно использовать в шаблонах для определения типа параметра шаблона:

// expre_typeid_Operator_3.cpp // compile with: /c #include template < typename T >T max( T arg1, T arg2 ) < cout arg2 ? arg1 : arg2 ); > 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *