[C con Clase] Un error con (¿...?) en GCC y no en Visual Studio (Parte III)

Steven Davidson srd4121 en njit.edu
Sab Jul 10 05:32:52 CEST 2010


Hola Gilberto,

Gilberto Cuba Ricardo wrote:
> Hola Lista,
> 
>   He mantenido este título porque sigo teniendo errores durante una
>   portación de códigos de Microsoft Visual Studio 2005 a GNU C/C++
>   Compiler 3.4x >. Esta vez no he dejado el tema de las plantillas en
>   el asunto porque a mi entender no lo es, pero no dejan de existir en
>   mi código.
> 
>   A continuación muestro la lógica seguida y la generación de los
>   códigos de errores que me van sucediendo. Una abstracción del código
>   inicial donde me da el problema es el siguiente:
> 

Veamos el código fuente.

>   ----------------------------------------------------
>   #include <string>
> 
>     class IClassTypeInfo
>       {
>         /* ... */
>       };
> 
>     template <class T>
>     class vmt_definition : public IClassTypeInfo
>       {
>         public:
>           template <typename RT>
>           void def_method(const std::string& name, RT (T::* fn) () )
>             {
>             }
>         /* ... */
>       };
> 
>     template < class Current, class Descendant >
>     struct definition;
> 
>     template <class T>
>     class ScriptType
>       {
>         public:
>           template<class U>
>           static IClassTypeInfo* resolve_definition()
>             {
> [1]              static definition<U, U> d_;

¿Estás seguro que quieres estos parámetros? Si es correcto, entonces es 
posible que quieras definir la plantilla 'definition' para cualesquier 
parámetros. De lo contrario, esta estructura debe ser: 
'definition<MyFirstClass,MyFirstClass>' o 
'definition<MyHeritClass,MyHeritClass>'.

>               return &d_;
>             }
>         /* ... */
>       };
> 
>     template <class T>
>     class BasicScriptable : public ScriptType<T>
>       {
>         typedef ScriptType<T> self_t;
>         /* ... */
>       };
> 
>     class HeritableClass : public BasicScriptable<HeritableClass>
>       {
>       public:
>         HeritableClass() {}
>       public:
>         void hered_first_method() {}
>         void hered_second_method() {}
>       };
> 
>     class MyFirstClass : public HeritableClass
>       {
>       public:
>         virtual void method01() {}
>       };
> 
>     class MyHeritClass : public MyFirstClass
>       {
>       public:
> [2]        virtual IClassTypeInfo* get_typeInfo() { return resolve_definition<MyHeritClass>(); }

Esto significa que se retornará la dirección de memoria del objeto 
estático de la estructura 'definition<MyHeritClass,MyHeritClass>'. Esta 
clase fue generada a partir de la especialización parcial que 
escribiste: 'struct definition<MyHeritClass, T>', donde T='MyHeritClass'.

>       public:
>         virtual void method_01() {}
>         virtual void method_02() {}
>       };
> 
> 
>   template<typename T>
>   struct definition<MyFirstClass, T> : public vmt_definition<T>
>     {
>       definition()
>         {
> [3]          def_method( "method1", &MyFirstClass::method01 );

Esto implica que los parámetros de 'def_method' serán RT='void' y 
T='MyFirstClass'. Esto también implica que invocas 
'vmt_definition<MyFirstClass>::def_method()'. Por consiguiente, esta 
plantilla debe ser 'definition<MyFirstClass, MyFirstClass>'. Sin 
embargo, debes ser explícito, ya que 'def_method()' no fue definida en 
este ámbito sino en otro. Deberías escribir:

this->vmt_definition<T>::def_method( "method1", &MyFirstClass::method01 );

Ten presente que los punteros a los miembros de una clase no siguen las 
reglas de herencia, sino de ámbito. Por lo tanto, el puntero a una 
función miembro de 'MyFirstClass' no es "transferible" a un puntero de 
otra clase.

El problema que estás teniendo es que instancias previamente un objeto 
de la clase 'definition<MyFirstClass, MyHeritClass>'. Esto no concuerda 
con lo que hemos mencionado antes y por tanto no encuentra una 
definición de 'def_method()' adecuada.

Podría escribir:

vmt_definition<MyHeritClass>::def_method( std::string("method1"), 
&MyHeritClass::method_01 );

Pero seguramente esto no es lo que querías hacer.

>         }
>     };
> 
>   template<typename T>
>   struct definition<MyHeritClass, T> : public definition<MyFirstClass, T>
>     {
>       definition()
> [4]        {
> [5]          def_method( "method_01", &MyHeritClass::method_01 );

Aquí tienes algo parecido al caso anterior. Puedes escribir:

definition<MyFirstClass, T>::def_method( "method_01", 
&MyHeritClass::method_01 );

>         }
>     };
> 
>   int main()
>   {
>     return 0;
>   }


Espero haber aclarado algo de este tema.

Steven






Más información sobre la lista de distribución Cconclase