È una buona idea "#definire me (* this)"?

20

Questa macro può essere definita in qualche intestazione globale, o meglio come parametro della riga di comando del compilatore:

#define me (*this)

E alcuni esempi di utilizzo:

some_header.h:

inline void Update()
{
    /* ... */
}

main.cpp:

#include "some_header.h"

class A {
public:
    void SetX(int x)
    {
        me.x = x;   
        me.Update(); 
    }

    void SomeOtherFunction()
    {
        ::Update();
    }

    /*
        100 or more lines
        ... 
    */

    void Update()
    {
        // ... 
    }

    int x;  
};

Quindi, in un metodo di classe quando accedo a un membro della classe, utilizzo sempre me , e quando accedo a un identificatore globale uso sempre :: . Questo dà al lettore che non ha familiarità con il codice (probabilmente io dopo pochi mesi) le informazioni localizzate su ciò a cui si accede senza la necessità di cercare altrove. Voglio definire me perché trovo che usare this-> ovunque sia troppo rumoroso e brutto. Ma può #define me (*this) essere considerato una buona pratica C ++? Ci sono alcuni punti problematici pratici con la macro me ? E se tu come programmatore C ++ sarai il lettore di un codice usando la macro me , ti piacerebbe o no?

Modifica: perché molte persone discutono in modo non specifico contro usando me , ma in generale contro esplicito questo. Penso che potrebbe non essere chiaro quali sono i vantaggi di "esplicitare questo ovunque".

Quali sono i vantaggi di "esplicito questo ovunque"?

  • Come lettore del codice hai la certezza di ciò a cui si accede e puoi concentrarti su cose diverse rispetto a verificare - in qualche codice remoto - che è realmente accessibile quello a cui pensi di aver accesso.
  • Puoi utilizzare la funzione di ricerca in modo più specifico. La ricerca " this->x " può darti risultati più ricercati rispetto alla sola ricerca " x "
  • Quando si elimina o si rinomina un membro, il compilatore ti avvisa in modo affidabile nei luoghi in cui viene utilizzato questo membro. (Alcune funzioni globali possono avere lo stesso nome ed esistono possibilità che tu possa introdurre un errore se non stai usando questo esplicito).
  • Quando si esegue il refactoring del codice e si esegue una funzione non membro dal membro (per rendere l'incapsulamento migliore) esplicita questo mostra quale posto è necessario modificare ed è possibile sostituirlo facilmente con il puntatore all'istanza della classe fornita come parametro della funzione non membro
  • Generalmente quando modifichi il codice, ci sono più possibilità di errori quando non lo usi esplicitamente rispetto a quando lo usi esplicitamente ovunque.
  • Esplicito questo è meno rumoroso dell'esplicativo "m_" quando si accede al membro dall'esterno ( object.member vs object.m_member ) (grazie a @Kaz per individuare questo punto)
  • Esplicito risolve questo problema universalmente per tutti i membri - attributi e metodi, mentre "m_" o altro prefisso è praticabile solo per gli attributi.

Vorrei lucidare ed estendere questo elenco, dimmi se conosci altri vantaggi e casi d'uso per esplicito questo ovunque .

    
posta user3123061 14.07.2014 - 08:18
fonte

5 risposte

89

No, non lo è.

Considera il programmatore che manterrà il tuo codice per molti anni da adesso, dopo che sarai partito per pascoli più verdi e segui le convenzioni comuni della lingua che usi. In C ++, non devi quasi mai scrivere this , perché la classe è inclusa nell'ordine di risoluzione dei simboli e quando viene trovato un simbolo nello scope della classe, this-> è implicito. Quindi non scrivere come fanno tutti.

Se si confondono spesso quali simboli derivano dall'ambito della classe, l'approccio usuale consiste nell'usare un modello di denominazione comune per i membri (campi e metodi a volte privati, non l'ho visto usato per i metodi pubblici). Quelli comuni includono il suffisso con _ o il prefisso con m_ o m .

    
risposta data 14.07.2014 - 08:38
fonte
41

Quindi, vuoi creare una nuova lingua. Allora fallo e non paralizzare C ++.

Ci sono diversi motivi per non farlo:

  1. Ogni normale standard di codifica suggerirà di evitare le macro ( ecco perché )
  2. È più difficile mantenere il codice con tali macro. Tutti quelli che programmano in C ++ sanno cos'è this , e aggiungendo tale macro, in realtà stai aggiungendo una nuova parola chiave. Cosa succede se tutti presentano qualcosa che gli piace? Come sarebbe il codice?
  3. Non dovresti usare (*this). o this-> , tranne in alcuni casi speciali (vedi questa risposta e cerca "this- >")

Il tuo codice non è diverso da #define R return , che ho visto nel codice reale. Ragionare? Meno digitando!

Sto andando leggermente fuori tema, ma qui ho intenzione di espandere il punto 3 (non usare (*this). o this-> in una classe).

Innanzitutto, (*this). o this-> vengono utilizzati per accedere alle variabili membro o alle funzioni dell'oggetto. Usarlo non ha senso e significa più digitazione. Inoltre, leggere questo codice è più difficile, perché c'è più testo. Ciò significa una manutenzione più difficile.

Quindi, quali sono i casi in cui devi utilizzare this-> ?

(a) Scelta sfavorevole del nome dell'argomento.

In questo esempio, è richiesto this-> , poiché l'argomento ha lo stesso nome della variabile membro:

struct A {
  int v;
  void foo( int v ) {
    this->v =v;
  }
};

(b) Quando si tratta di modelli ed ereditarietà (si veda questo )

Questo esempio non riuscirà a compilare, perché il compilatore non sa quale variabile denominata v per accedere.

template< typename T >
struct A {
  A(const T& vValue):v(vValue){}

  T v;
};

template< typename T >
struct B : A<T>
{
    B(const T& vValue):A<T>(vValue){}

    void foo( const T & newV ) {
      v = newV;
    }
};
    
risposta data 14.07.2014 - 08:37
fonte
25

Suggerisco di non farlo. Questo dà a un lettore che non ha familiarità con la tua macro un grande " WTF " ogni volta che lo vede. Il codice non diventa più leggibile quando si inviano "nuove convenzioni" su quelle generalmente accettate senza alcuna reale necessità.

using this-> everywhere is too noisy and ugly

Potrebbe sembrare così per te, forse perché hai fatto un sacco di programmazione in lingue usando la parola chiave me (Visual Basic, immagino?). Ma in realtà è solo una questione di abituarsi ad esso - this-> è piuttosto breve, e penso che la maggior parte dei programmatori C ++ esperti non saranno d'accordo con la tua opinione. E nel caso precedente, né l'uso di this-> o l'uso di me è appropriato: si ottiene la più piccola quantità di confusione lasciando fuori quelle parole chiave quando si accede ai membri dei dati all'interno delle funzioni dei membri.

Se vuoi che le tue variabili membro private siano distinte da quelle locali, aggiungi qualcosa link m_ come prefisso o un trattino basso come suffisso (ma come puoi vedere qui , anche questa convenzione è "troppo rumorosa" per molte persone).

    
risposta data 14.07.2014 - 08:36
fonte
17

Per favore non farlo! Sto cercando di far fronte a una grande base di codice in cui le macro sono dappertutto per salvare la digitazione. La cosa brutta di ridefinirlo è che il preprocessore lo sostituirà ovunque, anche dove non è in ambito / non si applica, ad esempio una funzione autonoma, il tuo collega potrebbe avere una variabile locale che mi ha chiamato da qualche altra parte. . (s) non sarà felice nel debug ... Finisci per avere macro che non puoi usare in tutti gli ambiti.

    
risposta data 14.07.2014 - 18:15
fonte
5

NO!

Immagina solo la confusione che si verificherà se qualcuno # include quella intestazione, non conoscendo il tuo trucco, e altrove nel loro file hanno una variabile o una funzione chiamata "me". Sarebbero orribilmente confusi da qualunque messaggio di errore imperscrutabile sarebbe stato stampato.

    
risposta data 15.07.2014 - 21:04
fonte

Leggi altre domande sui tag