C ++ получить динамический универсальный тип указателя? - PullRequest
3 голосов
/ 08 января 2010

название, вероятно, вводит в заблуждение, но я не знал, как его назвать.

допустим, у меня есть следующие структуры

template <typename T>
struct SillyBase{
   void doFunnyStuff(vector<T> vec){
        dummyField = T();
        for(int i=0; i<10; i++)
            vec.push_back(dummyField++);
    }
    T dummyField;
 };

struct A : public SillyBase<char>{};

struct B : public SillyBase<float>{};

Теперь давайте предположим, что у меня есть указатель

ISillyBase* ptr;

, который указывает на объект DECENDANT класса (A или B) из SillyBase - однако я НЕ ЗНАЮ какой из них (я просто знаю, что это либо A, либо B);

Есть ли для меня ЛЮБОЙ способ вызвать doFunnyStuff ()?

может быть что-то вроде:

vector<dynamic_generic_type_of(ptr)> vec;
ptr->doFunnyStuff(vec);

спасибо!

Ответы [ 6 ]

1 голос
/ 08 января 2010

В вашем примере вы не можете иметь SillyBase*, потому что SillyBase определяется как

template <typename T> struct SillyBase {...}

Так что вам нужно указать тип ...

Другая проблема заключается в том, что вы передаете копию vector<T> в doFunnyStuff(), которую затем заполняете ... это не кажется правильным, потому что, когда метод возвращает, вы теряете vec, если бы он был ссылкой 1011 *?

0 голосов
/ 08 января 2010

Я бы, наверное, выбрал ключевое слово dynamic_cast. Хотя вы столкнетесь с проблемой при объявлении вектора. Это должно быть типа SillyBase. Проблема в том, что это требует использования аргументов шаблона, которые были бы неизвестны и недоступны. Чтобы устранить эту проблему в прошлом, я просто поместил вектор в класс Base типа base, а затем предоставил функции для его изменения. Унаследованный класс предоставит переменную с тем же именем вектора в базовом классе. Унаследованный класс, наследующий функции базового класса, надеется заполнить правильный вектор. Я не знаю, хорошая это идея или плохая, но я пытался преодолеть эту проблему в своих проектах.

0 голосов
/ 08 января 2010

Я думаю, что вам нужна встроенная функция шаблона dynamic_cast. Он динамически определяет тип структуры данных и возвращает ноль, если это не экземпляр. Синтаксис

dynamic_cast<the_template_definition>(the_template_instantiation)

Один важный улов заключается в том, что классы шаблонов должны быть производными от общего виртуального класса. Таким образом, чтобы сделать то, что вы хотите, вы можете использовать следующий код:

#include <stdio.h>
class Top /* The parent class */ {
public: 
virtual ~Top() {}; // You need one base virtual function in the base class
};

template <typename T> class SillyBase : public Top {
   void doFunnyStuff(T dummyVar){
        dummyField  = dummyField + dummyVar;
    }
    T dummyField;
 };

class A : public SillyBase<char>{};
class B : public SillyBase<float>{};

int main(){
   A a;
   Top *ptr = (Top*)(&a);
   if(dynamic_cast<A*>(ptr) != NULL)
      printf("ptr is of type A*\n");
   if(dynamic_cast<B*>(ptr) != NULL)
      printf("ptr is of type B*\n");
   return 0;
}

Вывод программы будет:

ptr is of type A*
0 голосов
/ 08 января 2010

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

class SillyBaseBase
{
    public:
        void function doFunnyFunnyStuff(SillyBase<char> *)
        {
            SillyBase<char>::doFunnyStuff();
        }

        void function doFunnyFunnyStuff(SillyBase<float> *)
        {
            SillyBase<float>::doFunnyStuff();
        }

}
0 голосов
/ 08 января 2010

SillyBase *ptr; даже не должен компилироваться. Без списка параметров шаблона SillyBase не является типом, поэтому попытка использовать его в контексте, требующем типа, завершится неудачей.

Так как вы не можете создать указатель в первую очередь, нет реального ответа на то, как разыменовать его.

0 голосов
/ 08 января 2010

РЕДАКТИРОВАТЬ: даже с ISillyBase нет такой вещи, как виртуальные элементы шаблона, поэтому вы не сможете определить тот, который принимает vector<T> параметр.


Ну, в вашем примере нет такого не шаблонного типа, как SillyBase, поэтому вы не можете объявить SillyBase* ptr;

И, в конце концов, я не вижу, чего вы пытаетесь достичь: /

...