Доброго утра,Автоматического опущенными указателя на производный объект
У меня есть Шаблонный класс, и я хочу, чтобы манипулировать объекты вектора указателей. Чтобы использовать вектор указателей для шаблонизированного класса, мне нужен этот класс, который должен быть получен из неклассифицированного класса, и я это сделал.
Вот моя проблема: вызвать метод производного класса из указателя на базовый класс, я не могу использовать виртуальные функции, потому что функции шаблонов нельзя сделать виртуальными. Мне нужно сделать явный бросок, который является утомительным: как только создать числовой объект с новым, на самом деле, нужно сделать снимок для числа *, хотя известно, что объект является номером заранее.
Я решил эту проблему неловко: функция myset проверяет все поддерживаемые значения typeid для получения правильной динамической трансляции. Это длинная серия вложенных ifs, которые выполняют проверку типов.
Помимо утомительности функция работает только для вызова метода «set», а для вызова других методов должны быть определены аналогичные функции. Если бы я мог сделать автоматическое кастинг на тот объект, на который я указываю, все будет намного проще.
Недостатки этого подхода являются:
- код повторяется: если я определил другую функцию (например, Т получаем() {вернуться Val;}, я должен был бы еще одну функцию myget с полным набором гнездовых МФС!
- список поддерживаемых типов должны быть четко определены вложенности, если вызовы
- код может быть неэффективным
компилятор знает, что LST [0] (в коде ниже) указывает наumber объект, хотя lst является вектором объектов элемента, из которого выведены числа <>.
Есть ли способ автоматического понижения указателя, определенного как base *, указателю на объект, на самом деле направленный?
Если бы я был правильный понижающее приведение, то я мог бы определить тысячи методов числа <> класса и назвать их с propercasting функция -> (...) вызов
Вот код (он работает правильно , ядро определение «ой»)
Спасибо заранее, Pietro М.
PS Я в основном заинтересован в стандартном подходе C++ без использования других библиотек, кроме STL, таких как Boost.
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
class element
{
public:
virtual void print() = 0; // print is not templatized and works properly
//template <class T> virtual set(T v) = 0; // this would solve all my problems, if only it were legal.
};
template <class T>
class number : public element
{
T val;
public:
void print() {cout << "number is " << val << endl;}
void set(T v) {val = v;}
};
// That's the best I can do!
template <class T>
void myset(T v, element *ptr)
{
// There is a kink in the template: the compiler checks the T type by the value of v, that in this case is an integer:
// cout << "Type name for the template is: " << typeid(T).name() << endl;
// cout << "Type name for an integer is: " << typeid(int).name() << endl;
if (typeid(*ptr) == typeid(number<double>))
{
((number<double> *) ptr) -> set(7);
return;
}
else if (typeid(*ptr) == typeid(number<float>))
{
((number<float> *) ptr) -> set(7);
return;
}
// add other types... (tedious)
else
{
cout << "type not supported" << endl;
}
}
int main()
{
vector <element *> lst; // list of heterogeneous templatized objects
lst.push_back(new number<float>);
lst.push_back(new number<double>);
lst[0] -> print();
//((number<float> *) lst[0]) -> set(7); it's correct but it requires I know the type when I call it (tedious)
myset(7, lst[0]); // may be inefficient, but it works (for the types which are explicitly supported)
// cast_to_what_the_pointer_actually_points_to <lst[0]> -> set(7); // that's what I'd like to do: a downcast function which checks the object type and returns the correct pointer would be able to call any class method...
lst[0] -> print();
}
Таким образом, типы не имеют общего интерфейса (ну, кроме 'print'). Почему вы пытаетесь рассматривать их как таковые? (Альтернативно, вы можете использовать язык с динамической типизацией вместо C++) –
Я бы хотел, чтобы у них был общий интерфейс с использованием полиморфизма, но я не могу определить шаблон virtual void set (T) = 0; в базовом классе, потому что компилятор не хочет создавать виртуальные функции шаблона. Я не нашел способа определить виртуальную функцию внутри элемента, поэтому я надеялся, что смогу обойти это ограничение. –
pietrom79
Нет, это не похоже на то, что вы хотите. Вы не хотите, чтобы все подклассы имели функции для принятия * любых и всех типов * (это то, что будет означать виртуальная функция шаблона, и это также причина, по которой это запрещено). Первым шагом для решения этой проблемы является определение того, что вы хотите от этого. –