Недавно я решил поработать над проектом, в котором мне нужно иметь один объект, который может быть любого типа данных (uint8, unint16, uint32 или unint64) (я могу добавить, что это только цифры и будет только +, -, *, /, <<>> Я заглянул в Boost :: варианту, однако после того, как я его опробовал, он был обескуражен, так как не смог правильно извлечь данные. ааааа — подача заявок ?? Поэтому я посмотрел на другие методы, чтобы подражать этому.
Ниже этой точки эксперименты, и, кажется, неправильно, очень неправильно:
(Я хотел бы сказать, что я не слишком углублен в полиморфизм / наследование, поэтому извините заранее)
Я попытался создать базовый объект, а затем установить базовый объект на производный класс — класс производного шаблона, который является типом данных по моему выбору (uint8, uint16, uint32 или uint64). После этого я могу просто получить данные, которые Я ранее установил с помощью метода get ():
DynamicVariable *a = new TypedDynamicVariable<unsigned int>(12345);
std::cout << a->get() << std::endl;
delete a;
или же:
DynamicVariable *a = new TypedDynamicVariable<unsigned char>(255);
std::cout << a->get() << std::endl;
delete a;
пример представления:
unsigned int a = 100;
unsigned char b = 20;
std::cout << a + b << std::endl;
приводит к: ошибка C2039: «получить»: не является членом «DynamicVariable»
Я получаю ошибки, которых a-> get () не существует в классе BASE. Я искал в Интернете, чтобы найти этот код (dynamic_cast):
DynamicVariable *a = new TypedDynamicVariable<int>(12345);
TypedDynamicVariable<int>* p = dynamic_cast<TypedDynamicVariable<int>*>(a);
std::cout << p->get() << std::endl;
Как видите, это: TypedDynamicVariable *< int>* и dynamic_cast *> (a) (указав, что это INT) для меня побеждает всю цель того, что я хотел бы делать.
Ниже приведен класс, который я взломал вместе из-за многих неуверенных часов чтения онлайн. Кажется, у меня есть общее описание моего «решения», однако я действительно знаю, что отсутствует важное содержание, которое нуждается в улучшении или нуждается в улучшении, или на самом деле полиморфизм — это не то, что мне нужно, / я не могу его использовать.
class DynamicVariable
{
public:
//constructor & virtual destructor
DynamicVariable() {}
virtual ~DynamicVariable() {}
};
//unique data
template<typename T>
class TypedDynamicVariable : public DynamicVariable
{
private:
T _data;
public:
//constuctor
TypedDynamicVariable (const T& data) : _data(data) { }
//prototypes
void set (const T& data) { _data = data; }
T get (void) { return _data; }
};
Если кто-нибудь может помочь мне понять, что не так с приведенным выше классом, и направить меня к рабочему решению, или указать мне правильное направление с помощью Boost :: Вариант, если они действительно то, что я искал в конце концов.
Благодарю.
это
DynamicVariable *a = <some initialisation>
std::cout << a->get() << std::endl;
delete a;
не работает, потому что компилятор должен знать, как вызвать a->get()
не зная, какой производный тип a
на самом деле указывает на. По этой причине только те члены, которые являются частью a
объявленные (статические) типы рассматриваются и get
не один из них.
Это та же проблема, с которой сталкиваются Boost.Variant и Boost.Any.
В конце концов, все сводится к одной простой вещи: если вы не знаете, какой тип значения в настоящее время хранится в boost::variant<>
/boost::any
/DynamicVariable
тогда вы не сможете получить это значение.
Для Boost.Variant вы получаете значение с boost::get<type>(variant)
, Для Boost.Any вы получаете значение с boost::any_cast<type>(any)
, За DynamicVariable
вам, вероятно, придется сделать что-то подобное.
ты можешь использовать boost::variant
если определенные типы хорошо известны во время компиляции (вы должны предоставить список для его создания). и только тот типы могут быть сохранены в варианте. тогда вы можете использовать посетителей, чтобы сделать что-то с сохраненными данными (см. также which()
член-функция).
В качестве альтернативы вы можете использовать boost::any
без каких-либо ограничений на содержащиеся типы данных.
Написание собственного варианта (почти) невозможно реализовать в терминах традиционного ООП: Потому что вам нужно написать get()
член с другим типом возврата (неизвестно во время компиляции). (что невозможно в C ++).
и ваша текущая оболочка (в основном) бесполезна с точки зрения полиморфизма — вы можете иметь контейнер указателей на ваш базовый класс, но не можете понять, что хранится внутри … так что вы не можете get()
что-нибудь из этого хранилища с данными, хранящимися в нем. Вы должны предоставить несколько методов для этого. и они должны использовать RTTI как-то … так что с точки зрения производительности это будет далеко от совершенства … лучше использовать boost::variant
Чтобы иметь возможность звонить get()
из класса матери DynamicVariable
Вам нужно, чтобы этот метод был определен как виртуальный (чистый в вашем случае). Итак, вопрос в том, что это за тип get()
метод в DynamicVariable
вернется? Не пытайтесь найти фокус с шаблонами, виртуальные методы не могут быть шаблонами.
Я не большой поклонник boost :: variable или boost :: any (даже если они полезны!), Иногда это слишком простой способ решения проблем проектирования.
В качестве альтернативы я бы действительно подумал о приложении, которое вы имеете в виду (я думаю, что ваш пример упрощен). Задайте себе следующий вопрос: имеют ли разные типы общее значение?
get()
возвращает указатель на родительский класс, скажем GeneralReturnType
и дочерние реализации возвращают указатели на классы, которые являются производными от GeneralReturnType
,get()
от DynamicVariable
класс: другой тип возвращаемого значения не имеет общего значения, поэтому get()
Метод имеет различное значение в зависимости от класса TypedDynamicVariable
считается. Чтобы позвонить get()
метод, поэтому вы должны знать, какой у вас производный класс (возможно, полиморфизм — это не то, что вам нужно, действительно …).