Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Funciones y parametros

Iniciado por O2, 30 de Enero de 2003, 02:16:56 AM

« anterior - próximo »

O2

                                Necesito una funcion que pueda recibir diferentes tipos de punteros (concretamente punteros a diferentes tipos de clases)

Puedo hacer esto en una sola funcion mediante templates o algo asi?

Me explico mejor:

En vez de tener que usar un monton de versiones diferentes de la misma funcion:





void Function(CClassType1* p);

void Function(CClassType2* p);

...





Una funcion que pueda recibir punteros de varios tipos de clase, y sepa diferenciarlos y reconocerlos.

Como podria hacerlo?

Gracias de antemano!                                

metaxas

                                Fácil, te he hecho un pequeño ejemplo:



template<class T> int Function(T *ptr)

{

   return ptr->DoSomething();

}





class I

{

   public:

       virtual int DoSomething() = 0;

};





class A : public I

{

   public:

       virtual int DoSomething()

       {

           return 0;

       }

};





class B : public I

{

   public:

        virtual int DoSomething()

        {

            return 1;

        }

};



int main(int argc, char* argv[])

{

   A a;

   B b;

   int value1 = Function(&a); // value1 vale 0

   int value2 = Function(&b); // value2 vale 1



   return 0;

}


Para el tema de identificar el tipo, en vez de eso lo mejor es que hagas heredar las distintas clases de un interfaz común con las funciones que necesitas y las implementes en cada clase, como en el ejemplo.

Metaxas                                

O2

                                Que ocurriria si en tu ejemplo llamamos a Function con un puntero a un objeto que no tenga un metodo DoSomethig(); ?

Daria un error el compilador o petaria el programa?

Como podemos asegurarnos de que solo pueda llamarse a Function con unos determinados tipos de clases?

Gracias Metaxas!                                

Repoker

                               

#include <iostream.h>



template<class T> int Function(T *ptr)

{

   return ptr->DoSomething();

}





class I

{

   public:

       virtual int DoSomething() = 0;

};





class A : public I

{

   public:

       virtual int DoSomething()

       {

  cout << "Llamada clase A" << endl;

           return 0;

       }

};





class B : public I

{

   public:

        virtual int DoSomething()

        {

   cout << "Llamada clase B" << endl;

            return 1;

        }

};



int main(int argc, char* argv[])

{

   A a;

   B b;

   

cout << "+++ Llamadas estaticas +++" << endl;



int value1 = Function(&a); // value1 vale 0

   int value2 = Function(&b); // value2 vale 1



cout << endl;

cout << "+++ Llamadas dinamicas +++" << endl;



I* pointer;



pointer = new A;

pointer->DoSomething();



pointer = new B;

pointer->DoSomething();



   return 0;

}



Aqui tienes lo mismo pero usando llamadas dinámicas en vez de estáticas.                                

metaxas

                                O2, daría un error de compilación porque el objeto no tiene ese método. Respecto a tu última pregunta, precisamente en el ejemplo sólo puede llamarse a Function con un determinado tipo de clases, en concreto aquellas clases que implementan el interfaz. De esta forma, si pasases otras sabes en tiempo de compilación que estás pasando un puntero a un objeto que no es del tipo adecuado.

Metaxas                                

O2

                                Estupendo!

Todo solucionado. Muchas gracias a Metaxas y Repoker!!                                

ethernet

No es necesario el template, o usas template o usas metodos virtuales.

o sea


template <typename T> void func(T* p){

  p->funcion();

}





o bien



class Itfce {

public: virtual void  ifunc() = 0;

};

class B:public Itfce{  

void ifunc(){ std::cout << "holas";}

};

void funcion(Itfce *p){

p->ifunc();



}





Oh, boh,h epuestolo mismo  que repoker pero el  con codigo de ejemplo xDD. :_))
aunque las dos cosas juntas tb deben funcionar :DD

saludos

Juan Mellado

                                Nota: Al código de Repoker le falta un par de "delete pointer".

Quisquilloso soy :loco:                                

Repoker

                                Perdón perdón .. :P                                

O2

                                Queda todo aclarado, Gracias a todos :)                                

O2

                                Bueno, aclarado lo de los templates, ahora tengo otra duda :(

Necesito tener una lista enlazada de punteros a diferentes tipos de clases, de forma que solo necesite tener una variable PunterosAClases* Punteros; para referirme a todos los tipos de clases que pretendo.

Funcionaria con una union?



union uClassPointer

{

     ClassType1*,

     ClassType2*,

     ClassType3*,

};



Luego podria crear una lista enlazada de uClassPointer's y acceder a diferentes metodos y variables de diferentes clases mediante los punteros?

No se si lo que digo es completamente imposible :P

Gracias de nuevo!!                                

metaxas

                                Una forma de hacerlo, si no fueran muchas las clases distintas que puedes tener, sería hacer heredar esas clases de un interfaz común, obligando a implementar un método que devuelva el tipo al que pertenece la clase. En la lista guardarías punteros a la clase base común (el interfaz), y al pedir un elemento de la lista le pedirías el tipo y harías un cast al tipo adecuado en tiempo de ejecución, de esta forma:




#include <list>





enum { AType = 0, BType = 1 };





class IBase

{



public:

 

 virtual unsigned int GetType() = 0;

};





class A : public IBase

{

   

public:



unsigned int GetType()

{

    return AType;

}



void FuncA() {};

};





class B : public IBase

{

   

public:



unsigned int GetType()

{

    return BType;

}



void FuncB() {};

};







int main(int argc, char* argv[])

{

std::list<IBase *> ptrList;



A a;

B b;

ptrList.push_back(&a);

ptrList.push_back(&b);



IBase *ptrBase = ptrList.front();

unsigned int type = ptrBase->GetType();



switch (type)

{

 case AType: A *ptrA;

       ptrA = dynamic_cast<A *> (ptrBase);

       ptrA->FuncA();

       break;



 case BType: B *ptrB;

       ptrB = dynamic_cast<B *> (ptrBase);

       ptrB->FuncB();

       break;



 default: break;

}



return 0;

}


Acuérdate de compilarlo con el RTTI activado para que te funcione el dynamic_cast


Metaxas                                

O2

                                Gracias Metaxas! Algo asi estaba haciendo, pero no terminaba de cuajarlo.

Bueno, son bastantes tipos de clases, e ira en aumento, pero creo que es una buena forma de hacerlo.

Thnks de nuevo!                                






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.