литье — Как я могу удалить номер, связанный с typeid () .name () в C ++?

У меня есть класс метода фабрики, который генерирует «Предметы» и возвращает указатель на Предмет, который он создает.

Я получил классы 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;

Спасибо

5

Решение

Вы, вероятно, не должны использовать коды типов и переключения / 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());

Если рассматриваемый код на самом деле не принадлежит объекту, это может быть случай для посетитель шаблон.

4

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

typeid возвращает const std::type_info&, std::type_info тип имеет функцию с именем name который возвращает определяемое реализацией строковое представление имени базового типа. Нет абсолютно никаких гарантий относительно того, что эта функция будет возвращать — она ​​не должна возвращать строку, которая вообще выглядит как имя типа в исходной программе, и может декорировать ее так, как ей хотелось бы.

Если вам нужно отслеживать имя созданного вами типа, я бы предложил просто добавить виртуальную функцию, подобную этой, в вашу иерархию:

virtual std::string getType() const = 0;

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

Надеюсь это поможет!

8

Я использую 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

Я пришел к этому решению на основе ответа от этого сообщение что привело меня к этому статья.

2

Если вам просто нужно конвертировать указатели, вам не нужно создавать свой собственный идентификатор типа. Просто используйте dynamic_cast конвертировать указатель. Если тип не совпадает, вы получите нулевой указатель, и вы можете попробовать другой тип. Или вы можете сравнить typeid указателя и тому typeid каждого целевого типа напрямую.

Конечно, нет необходимости выполнять такой тип поиска во время выполнения.

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