2010-04-28 18 views
5

Digamos que tengo una estructuraConvert "esto" a una referencia a puntero

struct Foo { 
    void bar() { 
     do_baz(this); 
    } 
    /* See edit below 
    void do_baz(Foo*& pFoo) { 
     pFoo->p_sub_foo = new Foo; // for example 
    } 
    */ 

    Foo* p_sub_foo; 
} 

GCC me dice que

temp.cpp: In member function ‘void Foo::bar()’: 
temp.cpp:3: error: no matching function for call to ‘Foo::do_baz(Foo* const)’ 
temp.cpp:5: note: candidates are: void Foo::do_baz(Foo*&) 

Entonces, ¿cómo puedo convertir lo que es aparentemente un const Foo* a a Foo*&?

EDIT: No utilicé un muy buen ejemplo. do_baz debe leer

void do_baz(Foo*& pFoo) { 
    if (pFoo == NULL) { 
     pFoo = new Foo; 
     return; 
    } 
    //other stuff 
    do_baz(pFoo->p_sub_foo); 
    //more stuff 
} 
+2

acaba de deshacerse de la &. –

Respuesta

7

No puede.

En primer lugar, this no es necesariamente un const Foo *. this sería const Foo * es un método const de la clase Foo. En un método no const this es solo Foo *. (En realidad su mensaje de error menciona Foo* const. ¿Dónde viste const Foo *?)

En segundo lugar, y más importante aún, this no es un valor izquierdo. No puede tener un puntero a this. No puede tener una referencia no constante a this. Lo único que puede tener es una const reverence a this, es decir, una referencia de tipo Foo *const &.

(Foo *const &) funcionará en su caso.

void do_baz(Foo* const& pFoo) { 
    pFoo->p_sub_foo = new Foo; 
} 

Pero no veo el sentido de todo esto. Sólo declarar un puntero Foo * normal, como parámetro para su do_baz método

void do_baz(Foo* pFoo) { 
    pFoo->p_sub_foo = new Foo; 
} 

y obtener el mismo resultado. ¿Para qué crees que necesitas esa referencia?

EDITAR: Teniendo en cuenta su edición, lo que está tratando de hacer, no se puede hacer con una sola función do_baz, ya que en la primera llamada que le potencialmente (semánticamente) intento de modificar this, lo cual es imposible (incluso si el código de modificación nunca se ejecutará en la práctica). Ya sea que lo quiera o no, no puede tener una referencia no constante al this, incluso si no tiene la intención de escribir nada a través de él. Es probable que tenga que aplicar la primera llamada con una función diferente

void do_baz(Foo*& pFoo) { 
    if (pFoo == NULL) { 
    pFoo = new Foo; 
    return; 
    } 
    //other stuff 
    do_baz(pFoo->p_sub_foo); 
    //more stuff 
} 

void do_baz_root(Foo* pFoo) { 
    assert(pFoo != NULL); 
    //other stuff 
    do_baz(pFoo->p_sub_foo); 
    //more stuff 
} 

y luego hacer la primera llamada como

void bar() { 
    do_baz_root(this); 
} 
+0

La referencia sería porque en mi aplicación real, estaría asignando 'pFoo = new Foo;' Supongo que no representé tan bien ... –

+3

@Austin Hyde: Lo siento, pero eso simplemente no tiene sentido desde el punto C++ de vista. No puedes cambiar 'this'. 'this' no es modificable. ¿Qué intentabas implementar con ese código que intentaba cambiar 'this'? – AnT

+0

Se corrigió la pregunta. No intentaría modificar 'this', ya que estaría buscando' NULL'. Tuve un momento "doh" mientras escribía la pregunta. –

0

La palabra clave this no es un valor-I por lo this no se pueden asignar a/cambiado (independientemente de si lo que apunta es const o no). En otras palabras, es posible que pueda cambiar lo que apunta a this, pero no puede cambiar el valor de this. El estándar de C++ 9.3.2 "El puntero this":

En el cuerpo de un no estático (9.3) función miembro, la palabra clave this es una expresión no lvalue

Sólo las referencias const se pueden unir a los objetos no lvalue, por lo que se necesitaría para obligar a éste a un Foo* const& si desea enlazar el puntero this a una referencia.

cambiar la firma de la función a:

void do_baz(Foo* const& pFoo); 
4

Dar la variable un nombre, y entonces tendrá un tipo de referencia de puntero:

 
void bar() { 
    Foo* me = this; 
    do_baz(me); 
} 

También debo señalar que su do_baz función no está haciendo uso del hecho de que su parámetro es una referencia (no está asignando al puntero, solo, a lo que apunta el puntero). Por lo tanto, tiene más sentido cambiar el tipo de parámetro a Foo * en lugar de Foo * &, o hacerlo un Foo &, en cuyo caso usaría punto (.) En lugar de flecha (->) al desreferenciar el miembro del parámetro.

Editar
Su nueva versión de do_baz ahora hace uso del hecho de que el parámetro es una referencia. La solución anterior (simplemente usando un puntero con nombre) seguirá funcionando para su nueva versión del problema. Dicho eso, te aconsejaría en contra de lo que estás haciendo. Parece que está intentando insertar un elemento al final de una lista vinculada ...

En primer lugar, le aconsejaría que si está implementando una lista vinculada, mantenga no solo un puntero al primer nodo de la lista , pero también un puntero al último nodo en la lista en todo momento, de modo que la inserción al final de la lista se pueda realizar en tiempo constante. Sin embargo, si eso no es una posibilidad, le aconsejo que use una implementación iterativa en lugar de recursiva ya que es más simple y más clara. Se vería así:

 
Foo* current=this; 
while (current->next != NULL){ 
    current=current->next; 
} 
current->next = new Foo; 
0

No es así.

this es una Foo* const, lo que significa que es un puntero a una const no constFoo. Su referencia es no const, por lo que la declaración correcta sería Foo* const &.

Pero no tiene ningún sentido hacer esto, no lo haga.

Cuestiones relacionadas