2009-02-23 13 views
13

Ho programmato in C++ per molti anni e ho ancora dei dubbi su una cosa. In molti luoghi in altro codice persone che vedo qualcosa di simile:C'è qualche ragione per usare questo->

void Classx::memberfunction() 
{ 
    this->doSomething(); 
} 

Se ho bisogno di importare/utilizzare quel codice, ho semplicemente rimuovere la parte this->, e non ho mai visto niente di rotto o avere qualche effetti collaterali.

void Classx::memberfunction() 
{ 
    doSomething(); 
} 

Quindi, si conosce qualche motivo per utilizzare tale costrutto?

EDIT: Si noti che sto parlando delle funzioni membro qui, non delle variabili. Capisco che possa essere usato quando vuoi fare una distinzione tra una variabile membro e un parametro di funzione.

EDIT: apparente duplicato: Are there any reasons not to use "this" ("Self", "Me", ...)?

risposta

8

Per garantire l'attivazione degli errori del compilatore se è presente una macro che potrebbe essere definita con lo stesso nome della funzione membro e non si è certi se è stata definita indefinitamente.

No scherzo, sono abbastanza sicuro che ho dovuto fare esattamente questo per quel motivo!

+3

Nessuno sembra menzionare che un altro modo di risolvere i nomi dei membri è utilizzando http://en.wikipedia.org/wiki/Scope_resolution_operator. Per esempio. ClassX :: doSomething(); –

+7

Se applicato a una funzione ha l'effetto di garantire quale versione di una possibile funzione virtuale viene invocata, impedendo il polimorfismo e comunemente utilizzato per chiamare un genitore di una funzione sovrascritta. NON è un equivalente sicuro di questo-> doSomething(). –

+1

È vero, mi ero dimenticato di questo caso! Grazie Andy. –

2

mi viene in mente la leggibilità come quando si utilizza ulteriore parentesi di fare chiarezza.

1

Non penso che faccia la differenza per il compilatore, ma scrivo sempre questo-> perché credo che renda il codice autodocumentante.

2

Penso che sia principalmente un aiuto per il lettore. Rende esplicito che ciò che viene chiamato è un metodo sull'oggetto e non una funzione ordinaria. Durante la lettura del codice, può essere utile sapere che la funzione chiamata può modificare i campi nell'oggetto corrente, ad esempio.

25

Se esiste un'altra variabile con lo stesso nome con lo stesso nome, questo-> rimuoverà l'ambiguità.

void Bar::setFoo(int foo) 
{ 
    this->foo = foo; 
} 

Inoltre, è chiaro che si sta facendo riferimento a una variabile/funzione membro.

+0

Usarlo in questo modo è un cerotto per una cattiva convenzione di denominazione, a mio parere. Compensa il codice inutilmente. –

+4

Solo rispondendo alla domanda. – drby

+0

Non ho fatto una domanda sulle variabili, questo è un problema noto. Ho chiesto informazioni sulle funzioni dei membri. –

1

Disambiguazione: nel caso in cui si disponga di un'altra funzione/variabile di denominazione simile nello stesso spazio dei nomi? Non ho mai visto l'utilizzo per nessun altro motivo.

1

È la tua scelta. Trovo più chiaro quando lo usi. Ma se non ti piace, puoi ometterlo.

4

come "ragione codice", per distinguere un parametro o valore locale (che ha la precedenza) da un membro:

class Foo 
{ 
    int member; 
    void SetMember(int member) 
    { 
     this->member = member; 
    } 
} 

Tuttavia, questo è male practive per cominciare, e di solito possono essere risolti.

Il secondo motivo è più "ambiente": a volte aiuta Intellisense a filtrare quello che sto cercando. Comunque, anche io quando lo uso per trovare il membro che sto cercando, dovrei anche rimuoverlo.

Quindi sì, ci sono buone ragioni, ma sono tutte temporanee (e cattive a lungo termine).

+2

Non sono d'accordo sul fatto che questa sia necessariamente una cattiva pratica. Se hai un nome buono, chiaro e umboso per un oggetto o una variabile ... perché cambiarlo? –

+0

Lo standard di codifica IMO dovrebbe rendere inequivocabili le proprietà pubbliche rispetto ai membri interni rispetto a variabili/parametri locali. Per quanto odio digitare 'm_', c'è una buona ragione per questo. – peterchen

+0

Per chiarire: Penso che sia ok quando succede, ma quando capita spesso, è probabile che tu abbia un problema di leggibilità e un invito a bugs. Ora, il tuo standard potrebbe dichiarare 'questo->' essere sempre usato come 'il distinguo', ma non penso che sia una buona scelta. – peterchen

2

Questa è davvero una questione di stile e si applica a molti altri linguaggi come Java e C#. Alcune persone preferiscono vedere l'esplicito this (o o Me o altro) e altri no. Vai con quello che è nelle tue linee guida di stile, e se è il tuo progetto, devi decidere le linee guida.

+0

E alcuni linguaggi (PHP, Python) lo rafforzano. Uno dei motivi per cui odio fare OO in loro. –

1

Lo preferisco senza l'esplicito questo puntatore. Per le chiamate al metodo non aggiunge molto valore, ma aiuta a distinguere le variabili locali dalle variabili membro.

2

Questo viene fatto per essere espliciti circa il fatto che la variabile utilizzata è una variabile membro al contrario di una variabile locale o globale. Nella maggior parte dei casi non è necessario, ma essere espliciti riguardo all'ambito può essere utile se hai superato la variabile con una dichiarazione con lo stesso nome in un ambito più stretto.

Alle aziende in cui ho lavorato, abbiamo anteposto "m_" alle variabili membro. A volte può essere utile, e preferisco di gran lunga usare "questo->".

Modifica: Aggiunta di un collegamento a the GCC docs, che spiega un caso in cui l'utilizzo di questo -> è necessario per ottenere una ricerca non dipendente per funzionare correttamente.

35

L'unico posto dove veramente fa la differenza è nei modelli nelle classi derivate:

template<typename T> 
class A { 
protected: 
    T x; 
}; 

template<typename T> 
class B : A<T> { 
public: 
    T get() { 
    return this->x; 
    } 
}; 

causa details in the name lookup in C++ compilers, deve essere fatto esplicitamente chiarito che x è una (ereditata) membro della classe, fatto più facilmente con this->x. Ma questo è un caso piuttosto esoterico, se non si dispone di gerarchie di classi basate su modelli, non è necessario utilizzare esplicitamente this per accedere ai membri di una classe.

1

Non riesco a ricordare le circostanze esatte, ma ho visto casi (molto rari) in cui ho dovuto scrivere "questo-> nomeutente" per compilare correttamente il codice con GCC. Tutto ciò che ricordo è che non era in relazione all'ambiguità e quindi mi ci è voluto un po 'per capire la soluzione. Lo stesso codice compilato bene senza usare questo-> in Visual Studio.

+0

Ha a che fare con i parametri dipendenti del modello, questo link fornisce una buona spiegazione: http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html –

0

Lo userò per chiamare implicitamente gli operatori (i tipi di restituzione e di parametri sottostanti sono solo dei maniaci per la creazione del codice).

struct F { 
    void operator[](int); 
    void operator()(); 

    void f() { 
    (*this)[n]; 
    (*this)(); 
    } 

    void g() { 
    operator[](n); 
    operator()(); 
    } 
}; 

Mi piace la sintassi *this di più. Ha una semantica leggermente diversa, in quanto l'uso di *this non nasconderà le funzioni dell'operatore non membro con lo stesso nome di un membro, però.

+0

Che cosa intendi con "* questo" non nasconde le funzioni dell'operatore non membro con lo stesso nome di un membro "? Puoi fornire un esempio? – rlbond

+0

Esempio: 'struct A {void operator *(); void f(); }; void operator * (A, A); void A :: f() {A a; operatore * (a, a); } '<- Questo è mal formato, in quanto l'operatore membro * nasconde l'operatore globale *. Ma se scrivi 'a * a' (la sintassi dell'espressione), funzionerà correttamente, poiché la ricerca sarà separata per membri e non membri. –

+0

(Lo standard mostra un esempio migliore in 13.3.1.2/10). –

0

Ci sono molte buone risposte, ma nessuno di loro menziona che l'uso di questo-> nel codice sorgente rende più facile leggere, specialmente quando si legge un codice di qualche funzione lunga, ma anche una funzione breve, immagina un codice :

bool Class::Foo() 
{ 
    return SomeValue; 
} 

dall'osservazione di questo codice, non è possibile sapere chiaramente cos'è SomeValue.Potrebbe essere anche un po '# define o variabile statica, ma se si scrive

bool Class::Foo() 
{ 
    return this->SomeValue; 
} 

si sa chiaramente che SomeValue è una variabile membro non statica della stessa classe.

Quindi non ti aiuta solo a garantire che il nome delle tue funzioni o variabili non sia in conflitto con altri nomi, ma rende anche più facile per gli altri leggere e capire il codice sorgente, scrivendo un auto-documentare il codice sorgente è talvolta molto importante.

2

Un altro caso, che è arrivato sulle scene dopo C++ 11 è in lambda in cui viene catturato this.

Potrebbe essere qualcosa di simile:

class Example 
{ 
    int x; 
public: 
    std::function<void()> getIncrementor() 
    { 
    return [this]() -> void 
    { 
     ++(this->x); 
    } 
    } 
}; 

Anche se il lambda viene generato all'interno di una classe, si avrà accesso solo alle variabili locali da loro cattura (se il compilatore C++ fa 14) o catturare this . Nel secondo caso, all'interno del corpo di lambda, semplicemente non c'è x, ma solo this->x.

Problemi correlati