2010-04-28 14 views
5

Lassen Sie uns sagen, ich habe eine StrukturConvert „dieses“ eine Referenz-zu-Zeiger

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 mir sagt, dass

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*&) 

Also, wie konvertiere ich, was anscheinend ein const Foo* zu a Foo*&?

EDIT: Ich habe kein sehr gutes Beispiel verwendet. do_baz sollte lesen

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

nur loswerden der &. –

Antwort

7

Sie können nicht.

Erstens ist this nicht unbedingt eine const Foo *. this wäre eine const Foo * ist eine Const-Methode der Klasse Foo. Bei einer nicht-konstanten Methode ist this nur Foo *. (Ihre Fehlermeldung erwähnt eigentlich Foo* const. Wo haben Sie gesehen const Foo *?)

Zweitens, und noch wichtiger, this ist kein Lvalue. Sie können keinen Zeiger auf this haben. Sie können keinen nicht konstanten Verweis auf this haben. Das einzige, was Sie haben können, ist eine konstante Verehrung gegenüber this, d.h. eine Referenz des Typs Foo *const &.

Es (Foo *const &) wird in Ihrem Fall funktionieren.

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

Aber ich sehe nicht den Sinn von allem. erklären nur einen normalen Foo * Zeiger als Parameter für Ihre do_baz Methode

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

und das gleiche Ergebnis. Wofür brauchen Sie diese Referenz?

EDIT: Unter Berücksichtigung Ihrer bearbeiten, was Sie mit einem einzigen do_baz Funktion, da im ersten Aufruf getan werden kann, nicht zu tun versuchen würden Sie möglicherweise (semantisch) Versuch this, zu modifizieren, was unmöglich ist (auch wenn der modifizierende Code niemals in der Praxis ausgeführt wird). Ob Sie es wollen oder nicht, Sie können keinen nichtkonstanten Verweis auf this haben, auch wenn Sie nicht vorhaben, etwas damit zu schreiben. Sie werden wahrscheinlich den ersten Anruf mit einer anderen Funktion

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 
} 

und dann den ersten Anruf implementieren müssen, um als

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

Die Referenz wäre, weil ich in meiner tatsächlichen Anwendung 'pFoo = new Foo zuweisen würde;' Schätze, ich habe das nicht gut dargestellt ... –

+3

@Austin Hyde: Tut mir leid, aber das macht keinen Sinn von C++ Sicht. Sie können 'this' nicht ändern. 'dies' ist nicht veränderbar. Was versuchten Sie mit diesem Code zu implementieren, der versuchte, 'this' zu ändern? – AnT

+0

Die Frage wurde korrigiert. Ich würde nicht versuchen, 'this' zu ändern, da ich nach' NULL' suche. Ich hatte einen "Doh" -Moment beim Schreiben der Frage. –

0

Das Schlüsselwort this kein L-Wert ist so this kann nicht zugeordnet werden zu/geändert (unabhängig davon, ob das, worauf es hinweist, const oder nicht ist). Mit anderen Worten, Sie können möglicherweise ändern, was this Punkte auf, aber Sie können den Wert this nicht selbst ändern. Der C++ Standard 9.3.2 "Der this Zeiger":

Im Körper eines nichtstatischen (9.3) Member-Funktion, das Schlüsselwort this ist ein nicht-lvalue Ausdruck

Nur const Verweise auf Nicht-L-Wert-Objekte binden können, so dass Sie es zu einem Foo* const& zu binden brauchen würden, wenn Sie die this Zeiger binden mögen zu einer Referenz.

Ändern Sie die Signatur der Funktion zu:

void do_baz(Foo* const& pFoo); 
4

Geben Sie der Variablen einen Namen, und dann werden Sie einen Zeiger Referenztyp haben:

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

ich auch, dass Ihre do_baz möchte darauf hinweisen, Die Funktion nutzt nicht die Tatsache, dass ihr Parameter eine Referenz ist (Sie weisen dem Zeiger selbst nicht nur zu, worauf der Zeiger zeigt). Daher ist es sinnvoller, den Typ des Parameters in Foo * anstelle von Foo * & zu ändern oder es zu einem Foo & zu machen. In diesem Fall würden Sie beim Dereferenzieren den Punkt (.) Anstelle des Pfeils (->) verwenden das Mitglied des Parameters.

bearbeiten
Ihre neue Version von do_baz nutzt nun die Tatsache, dass der Parameter eine Referenz. Die obige Lösung (einfach mit einem benannten Zeiger) funktioniert immer noch für Ihre neue Version des Problems. Abgesehen davon würde ich davon abraten, was Sie tun. Es scheint, dass Sie versuchen, ein Element am Ende einer verketteten Liste einzufügen ...

Erstens würde ich empfehlen, dass wenn Sie eine verknüpfte Liste implementieren, die Sie nicht nur einen Zeiger auf den ersten Knoten in der Liste verwalten , aber auch immer einen Zeiger auf den letzten Knoten in der Liste, so dass die Einfügung am Ende der Liste in konstanter Zeit durchgeführt werden kann. Wenn dies jedoch nicht möglich ist, würde ich Ihnen dennoch raten, eine iterative Implementierung anstelle einer rekursiven zu verwenden, da diese sauberer und einfacher ist. Es würde aussehen:

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

Sie nicht.

this ist ein Foo* const, dh es ist ein Zeiger auf eine const nicht constFoo ist. Ihre Referenz ist nicht konstant, so dass die korrekte Deklaration eine Foo* const & wäre.

Aber es macht keinen Sinn, dies zu tun, also nicht.