virtuales sirve que puro puras propiedades poo polimorfismo para operadores new método metodos herencia funciones entre diferencia delete c++ templates virtual-functions

sirve - C++ pasando un tipo desconocido a una función virtual



polimorfismo puro c++ (4)

¿algo como eso?:

class Foo { virtual ~Foo() = 0; }; template <typename T> class Bar : public Foo { T object; } ... virtual void DoSomething(Foo* data) { Bar<int>* temp = dynamic_cast<Bar<int>*>(data); if (temp) std::count<<temp->object; }

Estoy escribiendo en C ++ y quiero pasar un tipo desconocido (conocido solo en tiempo de ejecución) a una función virtual pura:

virtual void DoSomething(??? data);

donde DoSomething es una implementación de una función virtual pura en una clase derivada.

Planeé usar plantillas pero, como resultado, la función virtual y las plantillas no funcionan juntas: ¿puede una plantilla de función miembro de la clase C ++ ser virtual?

Quiero evitar el uso de una clase base para todas las clases que pase a la función (algo así como el object en C #).

Gracias por adelantado


La eliminación de tipos no es la única posibilidad.

Tal vez le interese utilizar el patrón de visitante: tome como argumento una variante std :: y visítela con un lambda que contenga el código de plantilla que desea implementar:

virtual void doSomething(std::variant<int,float/*,...*/> data) { visit([=](auto v){/*...*/;},data); }


Necesita borrado de tipo . Un ejemplo de esto es el boost::any propósito general boost::any (y std::any en C ++ 17).

virtual void DoSomething(boost::any const& data);

Y luego, cada subclase puede intentar la any_cast segura de any_cast para obtener los datos que espera.

void DoSomething(boost::any const& data) { auto p = any_cast<std::string>(&data); if(p) { // do something with the string pointer we extracted } }

Por supuesto, puede implementar su propio tipo borrando la abstracción si el rango de comportamientos que busca es más limitado.


Si no desea utilizar boost / C ++ 17, considere derivar el parámetro de la función ''doSometing'' de una clase base y realice la conversión dinámica al objeto de clase correcto. En este caso, puede verificar en tiempo de ejecución que tiene un puntero válido.

class param{ public: virtual ~param(){}; }; template <typename T> struct specificParam:param{ specificParam(T p):param(p){} T param; }; class Foo { public: virtual void doSomething(param* data) = 0; }; template <typename T> class Bar : public Foo { public: virtual void doSomething(param* data){ specificParam<T> *p = dynamic_cast<specificParam<T> *>(data); if (p != nullptr){ std::cout<<"Bar got:" << p->param << "/n"; } else { std::cout<<"Bar: parameter type error./n"; } } }; int main(){ Bar<char> obj1; Bar<int> obj2; Bar<float> obj3; specificParam<char> t1(''a''); specificParam<int> t2(1); specificParam<float> t3(2.2); obj1.doSomething(&t1); //Bar got:a obj2.doSomething(&t2); //Bar got:1 obj3.doSomething(&t3); //Bar got:2.2 // trying to access int object with float parameter obj2.doSomething(&t3); //Bar: parameter type error. }

La forma más simple (¡pero insegura!) Sería usar void * puntero + transmisión estática

class Foo { public: virtual void doSomething(void* data) = 0; }; template <typename T> class Bar:public Foo { public: virtual void doSomething(void* data){ T* pData = static_cast<T*>(data); std::cout<<"Bar1 got:" << *pData << "/n"; } }; int main(){ Bar<char> obj1; Bar<int> obj2; Bar<float> obj3; char c = ''a''; int i = 1; float f = 2.2; obj1.doSomething(&c); // Bar1 got:a obj2.doSomething(&i); // Bar1 got:1 obj3.doSomething(&f); // Bar1 got:2.2 //obj2.doSomething(&c); // Very bad!!! }