2010-01-07 5 views
3

Название, вероятно, вводит в заблуждение, но я действительно не знал, как его назвать.C++ получение динамического универсального типа указателя?

скажем, у меня есть следующие структур

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; 

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

Есть ли способ для меня позвонить doFunnyStuff()?

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

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

спасибо!

+0

Проголосовало за закрытие как * не актуально *, потому что вопрос о том, как вызвать методы на 'ptr', основан на ошибочной предпосылке, что можно вообще объявить' ptr'. –

+0

Какова большая проблема? – GManNickG

+0

Какой «тип» вектора вы ожидаете пройти? и какие ценности вы хотите собрать? вы ожидали бы сохранить как символ, так и поплавки в векторе? поэтому вы все равно конвертируете их в один тип ... вероятно, есть простое решение вашей проблемы, но мы не знаем, в чем проблема, которую вы пытаетесь решить – stefanB

ответ

1

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

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

так что вам нужно чтобы обеспечить тип ...

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

+0

, которую вы могли бы иметь в ISillyBase виртуальном doFunnyStuff, но проблема в том, что что он должен знать тип параметра ... поэтому он не может быть виртуальным ... может быть, объяснить то, что вы пытаетесь достичь, и может быть проще решение. – stefanB

+0

ОК получилось - это не сработает так :) – genesys

0

EDIT: даже с ISillyBase, нет таких элементов, как элементы виртуального шаблона, поэтому вы не сможете определить тот, который принимает параметр vector<T>.


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

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

0

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

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

0

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

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

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

} 
0

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

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

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