У меня есть класс метода фабрики, который генерирует «Предметы» и возвращает указатель на Предмет, который он создает.
Я получил классы Item. Например, Предмет может быть «оружием», «расходным материалом» или «броней».
Мне нужно определить, какой тип Предмета создан, чтобы я мог правильно привести его к этому типу. Я сделал несколько тестовых строк, и похоже, что он делает то, что я хочу, за исключением добавления числа, связанного с типом.
У меня была строка:
cout << "Type Created: " << typeid(pItem).name() << endl;
Которые возвращают базовый класс Item, но он будет отображать: «4Item»
Затем я изменил это на:
cout << "Type Created: " << typeid(*pItem).name() << endl;
Что даст мне правильный производный тип, но также добавит это число. Итак, я получаю что-то вроде «5Armor»
Почему pItem вернул базовый класс? И почему он возвращает int с типом? Как я могу удалить int?
string type;
string returnedType = typeid(*pItem1).name();
for (int i=1; i < returnedType.length(); i++){
type.push_back(returnedType[i]);
}
cout << "type: " << type << endl;
Спасибо
Вы, вероятно, не должны использовать коды типов и переключения / downcasts для этого. Вместо этого поместите свой объектно-ориентированный код в виртуальный метод или (в зависимости от рассматриваемой проблемы) используйте шаблон посетителя. Ваш текущий подход, вероятно, будет выглядеть примерно так:
int price = 0;
if (obj->get_type_str() == "armor")
{
price = 1000 + ((Armor *)obj)->get_durability() * 100;
}
else if (obj->get_type_str() == "ninjasword")
{
price = 5000 * ((NinjaSword *)obj)->get_damage();
}
else if (obj->get_type_str() == "bfg")
{
price = 20000;
}
shop->show_price(price);
Проблема в том, что это не очень расширяемо. Вместо того, чтобы определять цену объекта вместе с объектом, он будет замусорен вокруг кода. Лучшим способом было бы предоставить виртуальный метод get_price (), который может сделать это:
class GameObject
{
public:
virtual ~GameObject() {}
virtual int get_price() const = 0;
};
class Armor: public GameObject
{
public:
virtual int get_price() const
{
return 1000 + durability * 100;
}
private:
int durability;
};
class NinjaSword: public GameObject
{
public:
virtual int get_price() const
{
return 5000 * damage;
}
private:
int damage;
};
class Bfg: public GameObject
{
public:
virtual int get_price() const
{
return 20000;
}
};
Теперь ваш объектно-ориентированный код остается в объекте, а предыдущий пример кода просто становится:
shop->show_price(obj->get_price());
Если рассматриваемый код на самом деле не принадлежит объекту, это может быть случай для посетитель шаблон.
typeid
возвращает const std::type_info&
, std::type_info
тип имеет функцию с именем name
который возвращает определяемое реализацией строковое представление имени базового типа. Нет абсолютно никаких гарантий относительно того, что эта функция будет возвращать — она не должна возвращать строку, которая вообще выглядит как имя типа в исходной программе, и может декорировать ее так, как ей хотелось бы.
Если вам нужно отслеживать имя созданного вами типа, я бы предложил просто добавить виртуальную функцию, подобную этой, в вашу иерархию:
virtual std::string getType() const = 0;
Эта функция может возвращать хорошее, удобочитаемое представление типа, который, как гарантированно, будет вести себя так, как вы хотите (потому что вы несете ответственность за его написание).
Надеюсь это поможет!
Я использую g ++ и тоже имел эту проблему. Теперь, строго отвечая на ваш вопрос без какого-либо намерения указать наилучший подход, есть еще один способ разобраться с этим делом.
Вот пример копирования / вставки для вас:
Создайте свой тип, например, MyType.h
#ifndef __MYTYPE_H__
#define __MYTYPE_H__
class MyType {
};
#endif
и файл main.cpp, например так:
#include <cxxabi.h>
#include <iostream>
#include <typeinfo>
#include "MyType.h"
template <typename T> char* get_typename(T& object)
{
return abi::__cxa_demangle(typeid(object).name(), 0, 0, 0);
}
int main(int argc, char ** argv)
{
MyType my_type;
std::cout << get_typename(my_type) << std::endl;
return 0;
}
Это вывело бы: MyType
Я пришел к этому решению на основе ответа от этого сообщение что привело меня к этому статья.
Если вам просто нужно конвертировать указатели, вам не нужно создавать свой собственный идентификатор типа. Просто используйте dynamic_cast
конвертировать указатель. Если тип не совпадает, вы получите нулевой указатель, и вы можете попробовать другой тип. Или вы можете сравнить typeid
указателя и тому typeid
каждого целевого типа напрямую.
Конечно, нет необходимости выполнять такой тип поиска во время выполнения.