Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 35, средняя оценка - 4.71
Sanek911
4 / 4 / 0
Регистрация: 04.12.2009
Сообщений: 42
#1

Как узнать, какого типа объект находится по указателю - C++

26.03.2012, 23:31. Просмотров 5608. Ответов 22
Метки нет (Все метки)

Есть массив указателей базового класса, нужно узнать какие типы этих объектов.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Shape{
public:
  ~Shape(){}
  virtual void Draw() = 0;
};
class Triangle : public Shape{
  virtual void Draw(){}
};
class Circle : public Shape{
  virtual void Draw(){}
};
class Square : public Shape{
  virtual void Draw(){}
};
 
void main()
{
  std::vector<Shape *> vec;
  for(int i = 0; i < 10; i++){
    if ((i % 3) == 0)
      vec.push_back(new Triangle());
    if ((i % 3) == 1)
      vec.push_back(new Circle()); 
    if ((i % 3) == 2)
      vec.push_back(new Square());
  }
//предложите код который поможет узнать типы объектов в векторе
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.03.2012, 23:31
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как узнать, какого типа объект находится по указателю (C++):

Как удалить объект по указателю на базовый класс? - C++
Допустим есть несколько классов: // абстрактный класс - введен для управления наследниками class A{ ... } // рабочий класс...

вызов конструктора, по указателю на объект - C++
class qwe { public: qwe() {} qwe(char * name, int a, int b):_name(strdup(name)), _a(a), _b(b) {} private: char * _name; ...

Узнать значение по указателю - C++
Пишу плагин для gta 3. В Cheat Engine я нашел нужный адрес, но он оказался динамическим.CE вычислил такой поинтер: Вопрос: как...

Как узнать, находится ли std::cout в hex-режиме? - C++
Как узнать, находится ли std::cout в hex-режиме?

интерфейс, в методе которого создается объект типа IDictionary и возвращается ссылка на этот объект - C++
Привет всем. Необходимо реализовать интерфейс, в методе которого создается объект типа IDictionary и возвращается ссылка на этот объект. Не...

Как инициализировать объект типа std::deque<int>? - C++
Доброе время суток! Я видимо совсем не разбираюсь в шаблонах, так как не понимаю почему не работает:std::deque&lt;int&gt; d = {1, 2, 3, 4, 5}; ...

22
DU
1483 / 1129 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
26.03.2012, 23:34 #2
смотрите описание к оператору dynamic_cast. позволяет кастить указатель на базу к указателю на производный класс с проверкой. если производный имеет нужный тип, то скастится, иначе оператор вернет нуль или кинет исключение при преобразовании ссылок.
1
igorrr37
1647 / 1275 / 133
Регистрация: 21.12.2010
Сообщений: 1,932
Записей в блоге: 7
27.03.2012, 01:50 #3
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>
#include <typeinfo>
 
class Shape
{
public:
    ~Shape(){}
    virtual void Draw() = 0;
};
 
class Triangle : public Shape
{
public:
    virtual void Draw(){}
};
 
class Circle : public Shape
{
public:
    virtual void Draw(){}
};
 
class Square : public Shape
{
public:
    virtual void Draw(){}
};
 
int main()
{
    std::vector<Shape*> vec;
    for(int i = 0; i < 10; i++)
    {
        if ((i % 3) == 0) vec.push_back(new Triangle());
        if ((i % 3) == 1) vec.push_back(new Circle());
        if ((i % 3) == 2) vec.push_back(new Square());
    }
    for(auto p : vec)
    {
        std::cout << typeid(*p).name() << std::endl;
    }
    return 0;
}
3
Миниатюры
Как узнать, какого типа объект находится по указателю  
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
27.03.2012, 06:15 #4
Полиморфизм нужен для того, чтобы игнорировать действительный тип объектов и работать только с базовым.
0
dqrest
2 / 2 / 0
Регистрация: 06.01.2012
Сообщений: 115
12.11.2012, 10:01 #5
Если не хочешь разбираться с кастами и полиморфизмом, то заведи переменную в базовом классе флаг и с помощью него можешь узнавать тип уазателя
1
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
12.11.2012, 12:19 #6
Тут нужна динамическая идентификация типов что-то такое:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <cxxabi.h>
#include <stdio.h>
#include <vector>
using namespace std;
 
class Shape{
public:
  ~Shape(){}
  virtual void Draw() = 0;
};
class Triangle : public Shape{
  virtual void Draw(){}
};
class Circle : public Shape{
  virtual void Draw(){}
};
class Square : public Shape{
  virtual void Draw(){}
};
 
int main()
{
  std::vector<Shape *> vec;
  for(int i = 0; i < 10; i++){
    if ((i % 3) == 0)
      vec.push_back(new Triangle());
    if ((i % 3) == 1)
      vec.push_back(new Circle()); 
    if ((i % 3) == 2)
      vec.push_back(new Square());
  }
 
 //собсно идентификация: 
 
 int status;
 char* realname;
 
 realname = abi::__cxa_demangle(typeid(*vec[0]).name(), 0, 0, &status);
 printf (realname);
 getchar ();
 
 realname = abi::__cxa_demangle(typeid(*vec[1]).name(), 0, 0, &status);
 printf (realname);
 getchar ();
 
 realname = abi::__cxa_demangle(typeid(*vec[2]).name(), 0, 0, &status);
 printf (realname);
 getchar ();
 
 
 
}

Дополнительно смотреть:
http://khpi-iip.mipk.kharkiv.edu/lib...dt/glava12.pdf
http://gcc.gnu.org/onlinedocs/libstd...1pt12ch39.html
http://www.cplusplus.com/reference/s...nfo/type_info/
Определить все данные, тип которых вводится из командной строки
Определение введенного типа
0
Завернин
1 / 1 / 0
Регистрация: 22.12.2013
Сообщений: 27
23.01.2015, 19:44 #7
Deviaphan, вы давно программируете? Категорически с Вами не согласен. Полиморфизм нужен как для использования общих виртуальных функций, так и для уникальных для каждого потомка. То есть это абсолютно рядовая задача программирования делать коллекцию базовых объектов и в дальнейшем преобразовывать их в потомки для дальнейшей обработки.
Вот один из множества примеров, взятых из реальной жизни: у Вас есть коллекция графических примитивов в виде линий и дуг, основанных на одном общем родительском классе gElement. Попробуйте написать функцию, находящую точки пересечения двух произвольных элементов, принимающую в качестве аргументов ссылки на gElement (double[] Intersection(gElement el1, gElement el2), не прибегая к преобразованию базовых элементов к родительским типам.

Добавлено через 23 минуты
А по топику полностью согласен с DU - нужно использовать dinamic_cast.
Ответ dqrest тоже хорош, можно завести переменную, перечисляющую родительские типы и указывающую явно в какой тип надо преобразовать, что увеличит скорость выполнения при увеличении количества наследников. В этом случае можно будет использовать static_cast или явное преобразование - это еще прирост скорости.
0
Voivoid
675 / 278 / 12
Регистрация: 31.03.2013
Сообщений: 1,339
23.01.2015, 21:41 #8
Цитата Сообщение от Завернин Посмотреть сообщение
не прибегая к преобразованию базовых элементов к родительским типам
Двойная диспетчеризация.

А dynamic_cast'ы и прочие "завести переменную" нужны только неосиляторам которые не могут спроектировать систему типов.
0
mishelle92
62 / 61 / 20
Регистрация: 09.10.2012
Сообщений: 201
Завершенные тесты: 1
23.01.2015, 23:53 #9
Цитата Сообщение от Voivoid Посмотреть сообщение
Двойная диспетчеризация.
Можно пример кода увидеть? Не пойму как это решит вопрос ТС-а.

Или имелось в виду, что решать задачу "Есть массив указателей базового класса, нужно узнать какие типы этих объектов." саму по себе не имеет смысла?
0
Voivoid
675 / 278 / 12
Регистрация: 31.03.2013
Сообщений: 1,339
24.01.2015, 14:09 #10
Цитата Сообщение от mishelle92 Посмотреть сообщение
Можно пример кода увидеть? Не пойму как это решит вопрос ТС-а.
Вопрос ТС'а это никак не решит. Я неудачно процитировал, это ответ на вопрос:
Цитата Сообщение от Завернин Посмотреть сообщение
Попробуйте написать функцию, находящую точки пересечения двух произвольных элементов



А ответ на вопрос ТС'а простой - не нужно знать типы этих объектов.
1
Завернин
1 / 1 / 0
Регистрация: 22.12.2013
Сообщений: 27
20.02.2015, 16:20 #11
Цитата Сообщение от Voivoid Посмотреть сообщение
Двойная диспетчеризация.
А dynamic_cast'ы и прочие "завести переменную" нужны только неосиляторам которые не могут спроектировать систему типов.
Для двойной диспетчеризации нужно знать какого типа объекты взаимодействуют. Она также не будет работать с коллекцией объектов базового типа. Если вы считаете такие коллекции бессмыленными - это ваш личный подход. Возможно вы предпочитаете писать на чистом С. С точки зрения ООП такие коллекции полностью оправданы и позволяют реализовать многие возможности ООП. Возможно вы неправильно понимаете идеологию ООП.
0
hoggy
6636 / 2821 / 484
Регистрация: 15.11.2014
Сообщений: 6,240
Завершенные тесты: 1
20.02.2015, 16:57 #12
Цитата Сообщение от Завернин Посмотреть сообщение
Deviaphan, вы давно программируете?
Учитывая, что последняя запись от господина kravam датирована 2012 годом, то как минимум 3 года.

А учитывая общую подкованность господина Deviaphan,
то можно смело предположить, что он и в 2012 уже был специалистом.
---------------------------------------------------------------

Цитата Сообщение от Завернин Посмотреть сообщение
Возможно вы предпочитаете писать на чистом С. С точки зрения ООП такие коллекции полностью оправданы и позволяют реализовать многие возможности ООП. Возможно вы неправильно понимаете идеологию ООП.
А вот ваши ответы красноречиво намекают: вы не умеете ооп.

1. Язык си, со своей процедурной парадигмой не имеет никакого отношения к ответа господина Deviaphan.

2. Технология полиморфизм, на которой базируется оо-парадигма,
была разработана, что бы реализовать идеому: "закрыт для изменений, открыт для расширений".

Другими словами, полиморфизм для того и нужен, что бы избежать необходимости пасти фактические типы,
и уйти от километровых свитч-кейсов, и армии ифов.

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

Это дает основание предположить, что вы сами не понимаете ООП.

Более того: именно к вам можно обратить ваш собственный тезис:

С точки зрения ООП ваш юзкейс нарушает идеому "зарыт для изменений, открыт для расширений",
и прекрасно реализуется на обычном процедурном си при помощи свит-кейсов,
или конструкций из if/else, имея при этом все их недостатки.

Возможно вы предпочитаете писать на чистом С.
Возможно вы просто неправильно понимаете идеологию ООП.
Но такие коллекции не оправданы с точки зрения ООП,
и ломают на корню многие из его возможностей.

Что-то подобное в оо-архитектуре красноречивый признак её ущербности.
1
Завернин
1 / 1 / 0
Регистрация: 22.12.2013
Сообщений: 27
20.02.2015, 21:47 #13
Цитата Сообщение от hoggy Посмотреть сообщение
Более того: именно к вам можно обратить ваш собственный тезис:
С точки зрения ООП ваш юзкейс нарушает идеому "зарыт для изменений, открыт для расширений",
Согласен, принцип открытости-закрытости может нарушаться в абстрактных коллекциях.
С теоретической точки зрения да, если нам нужна динамическая типизация, то мы не соблюдаем этот принцип.

Но программирование прежде всего имеет смысл с точки зрения практики.
И не спроста язык предлагает нам инструменты динамической типизации вроде dinamic_cast и typeid.
Можно обойтись и без таких коллекций, только это усложнит реализацию.

Лучше рассмотреть на конкретной задаче:
Есть 2 контура Contour, состоящих из последовательно соединенных линий Line: Element и дуг Arc: Element.
Нам нужно найти точки пересечения этих контуров.

Архитектурное решение с применением абстрактных коллекций: Перечисляем элементы первого контура, для каждого из них перечисляем все элементы второго контура и вызываем у них метод PointF pf = el1.Intersect(el2);
В методе Intersect каждого типа пишем свич-кейсы. Нарушаем принцип открытости-закрытости (при добавлении новых типов примитивов придется дописывать свич-кейсы в каждом "братском" классе), но простота реализации и поддержки, а также скорость выполнения программы при большом количестве элементов (касты делаются быстро, по крайней мере на C#).

Какую можете предложить альтернативу? (Естественно в приватных функциях контура должны сохраняться возможности вставки, удаления, инверсии элементов, и желательно доступа к элементу по индексу).

Добавлено через 39 минут
Архитектурное решение с применением абстрактных коллекций: Вызываем метод cont1.Intersect(cont2); Перечисляем элементы первого контура, приводим к производному типу. Для каждого из них перечисляем все элементы второго контура, приводим их и вызываем метод PointF pf = (line1/arc1).Intersect(line2/arc2);
Все свич-кейсы пишутся в методе Contour.Intersect. При добавлении новых типов примитивов, нужно будет дописать свич кейсы только этого метода, а ранее написанный код примитивов останется без изменений.
В такой реализации не нарушается принцип открытости-закрытости, но остается простота реализации и поддержки, а также скорость выполнения программы при большом количестве элементов (касты делаются быстро, по крайней мере на C#).

А вот избавиться от динамической типизации вряд ли получится. Отказываться от абстрактной коллекции тоже смысла не вижу и не считаю это ущербным. В принципах ООП ничего нет про ущербность абстрактных коллекций=)
0
Voivoid
675 / 278 / 12
Регистрация: 31.03.2013
Сообщений: 1,339
20.02.2015, 23:35 #14
Цитата Сообщение от Завернин Посмотреть сообщение
Для двойной диспетчеризации нужно знать какого типа объекты взаимодействуют. Она также не будет работать с коллекцией объектов базового типа
Лолшто? Ты похоже вообще не шаришь о чем идет речь. На вот, просветись что-ли, довольно приятная реализация мультиметодов на плюсах: https://github.com/jll63/yomm11
1
Croessmah
Эксперт CЭксперт С++
13408 / 7558 / 853
Регистрация: 27.09.2012
Сообщений: 18,590
Записей в блоге: 3
Завершенные тесты: 1
20.02.2015, 23:39 #15
Цитата Сообщение от Voivoid Посмотреть сообщение
На вот, просветись что-ли, довольно приятная реализация мультиметодов на плюсах
да у Александресску тоже нормально расписано. Можно сначала к его труду отослать
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.02.2015, 23:39
Привет! Вот еще темы с ответами:

Не удаётся создать безымянный объект типа vector моего типа - C++
Собсно #include &lt;vector&gt; using namespace std; //Вот мой австорский тип struct kletka { int i, j; kletka(int x, int...

Как привести объект пользовательского типа к заданному встроенному типу? - C++
Добрый вечер, у меня есть класс: ref class MessageClass { public: char *senderName; short sizeMessage; char *message;

Какого типа std::endl ? Как сделать так, чтобы функция могла принимать endl в качестве аргумента? - C++
Что надо указать в прототипе функции, чтобы можно передавать std::endl в качестве аргумента? Уже 3 часа голову ломаю! :wall: Помогите,...

Как передавать значения строкового типа в конструктор через объект класса? - C++
Как передавать значения строкового типа в конструктор через объект класса? Или просто, как передавать знач строкового типа в конструктор? ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
20.02.2015, 23:39
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru