2009-02-23 24 views
13

He programado en C++ durante muchos años y todavía tengo dudas sobre una cosa. En muchos lugares de otro código de la gente que veo algo así como:¿Hay alguna razón para usar esto->

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

Si necesito para importar/usar ese código, basta con quitar la parte this->, y nunca he visto nada roto o tener algún efectos secundarios.

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

Entonces, ¿conoce alguna razón para usar tal construcción?

EDITAR: Tenga en cuenta que estoy hablando de funciones de miembros aquí, no de variables. Entiendo que se puede usar cuando quiera hacer una distinción entre una variable miembro y un parámetro de función.

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

Respuesta

8

Para garantizar que se activa errores de compilación si hay una macro que podría definirse con el mismo nombre que su función de miembro y no está seguro de si ha sido fiable indefinido.

No es broma, estoy bastante seguro de que he tenido que hacer exactamente esto por eso!

+3

Nadie parece mencionar que otra forma de resolver los nombres de los miembros es utilizando el http://en.wikipedia.org/wiki/Scope_resolution_operator. P.ej. Classx :: doSomething(); –

+7

Si se aplica a una función, tiene el efecto de garantizar qué versión de una función posiblemente virtual se invoca, lo que previene el polimorfismo y se usa comúnmente para llamar a un padre de una función anulada. NO es un equivalente seguro de esto-> doSomething(). –

+1

¡Es verdad, había olvidado este caso! Gracias Andy. –

2

se me ocurre la legibilidad como cuando se utiliza el paréntesis adicional para dejar las cosas claras.

1

No creo que haga una diferencia en el compilador, pero siempre escribo esto-> porque creo que hace que el código se auto-documente.

2

Creo que es principalmente como una ayuda para el lector. Hace explícito que lo que se llama es un método en el objeto, y no una función ordinaria. Al leer el código, puede ser útil saber que la función llamada puede cambiar campos en el objeto actual, por ejemplo.

25

Si hay otra variable en el mismo ámbito con el mismo nombre, this-> eliminará la ambigüedad.

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

También deja en claro que se está refiriendo a una variable/función miembro.

+0

Usarlo así lo hace una curita para una mala convención de nombres, en mi opinión. Agrupa el código innecesariamente. –

+4

Respondiendo la pregunta. – drby

+0

No hice una pregunta sobre variables, es un problema conocido. Pregunté sobre las funciones de los miembros. –

1

Desambiguación: en caso de que tenga otra función/variable de denominación similar en el mismo espacio de nombres? Nunca he visto el uso por ninguna otra razón.

1

Es su propia elección. Lo encuentro más claro cuando usas esto. Pero si no te gusta, puedes omitirlo.

4

Como "código de razón", para distinguir un parámetro o valor local (que tiene prioridad) de un miembro de:

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

Sin embargo, eso es malo practive para empezar, y por lo general pueden ser resueltos a nivel local.

La segunda razón es más "entorno": a veces ayuda a Intellisense a filtrar lo que realmente estoy buscando. Sin embargo, también creo que cuando use esto para encontrar el miembro que estoy buscando también debería eliminarlo.

Así que sí, hay buenas razones, pero todas son temporales (y malas en el largo plazo).

+2

No estoy de acuerdo con que esto sea necesariamente una mala práctica. Si tiene un nombre bueno, claro y sombrío para un objeto o variable ... ¿por qué cambiarlo? –

+0

El estándar de codificación IMO debe hacer que las propiedades públicas frente a los miembros internos frente a las variables/parámetros locales sean poco ambiguas. Por mucho que odie escribir 'm_', hay una buena razón para ello. – peterchen

+0

Para aclarar: creo que está bien cuando sucede, pero cuando sucede a menudo, es probable que tenga un problema de legibilidad y una invitación a los errores de deslizamiento de atención. Ahora, su estándar podría declarar que 'this->' se usará siempre como 'el distinguidor', pero no creo que sea una buena opción. – peterchen

2

Esto es realmente una cuestión de estilo y se aplica a muchos otros lenguajes como Java y C#. Algunas personas prefieren ver el this explícito (o self, o Me, o lo que sea) y otros no. Simplemente haga lo que esté en sus pautas de estilo, y si es su proyecto, puede decidir las pautas.

+0

Y algunos idiomas (PHP, Python) incluso lo hacen cumplir. Una de las razones por las que odio hacer OO en ellas. –

1

Lo prefiero sin el explícito este puntero también. Para llamadas de método, no agrega mucho valor, pero ayuda a distinguir las variables locales de las variables de miembro.

2

Esto se hace para ser explícito sobre el hecho de que la variable que se utiliza es una variable miembro en contraposición a una variable local o global. No es necesario en la mayoría de los casos, pero ser explícito sobre el alcance podría ser útil si ha superado la variable con una declaración del mismo nombre en un ámbito más estricto.

En las empresas en las que he trabajado, sólo antepone "m_" a variables miembro. A veces puede ser útil, y prefiero usar "this->".

Editando: Añadiendo un enlace a the GCC docs, que explica un caso donde usar this-> es necesario para que una búsqueda no dependiente funcione correctamente.

35

El único lugar en el que realmente hace la diferencia está en las plantillas en las clases derivadas:

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

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

Debido a details in the name lookup in C++ compilers, tiene que quedar claro que x es un (heredado) miembro de la clase, más fácil de hacer con this->x. Pero este es un caso bastante esotérico, si no tiene jerarquías de clases con plantillas, realmente no necesita usar explícitamente this para acceder a los miembros de una clase.

1

No puedo recordar bien las circunstancias exactas, pero he visto casos (muy raro) donde tuve que escribir "this-> MemberName" para compilar correctamente el código con GCC. Todo lo que recuerdo es que no estaba relacionado con la ambigüedad y, por lo tanto, me tomó un tiempo encontrar la solución. El mismo código compilado bien sin usar this-> en Visual Studio.

+0

Tiene que ver con los parámetros de la plantilla dependiente, este enlace ofrece una buena explicación: http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html –

0

lo voy a utilizar para llamar a los operadores de forma implícita (el retorno y parámetros de los tipos siguientes son sólo maniquíes para la confección del código).

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

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

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

me gusta la sintaxis *this más. Tiene una semántica ligeramente diferente, ya que usar *this no ocultará las funciones del operador no miembro con el mismo nombre que un miembro.

+0

¿Qué quiere decir "' * this' no ocultará las funciones del operador no miembro con el mismo nombre que un miembro "? ¿Puede dar un ejemplo? – rlbond

+0

Ejemplo: 'struct A {void operator *(); void f(); }; operador vacío * (A, A); void A :: f() {A a; operador * (a, a); } '<- esto está mal formado, ya que el operador miembro * oculta el operador global *. Pero si escribe 'a * a' (la sintaxis de expresión), funcionará bien, ya que la búsqueda será independiente para miembros y no miembros. –

+0

(El estándar muestra un mejor ejemplo en 13.3.1.2/10). –

0

Hay muchas buenas respuestas, pero ninguna de ellas menciona que usar this-> en el código fuente hace que sea más fácil de leer, especialmente cuando estás leyendo un código de alguna función larga, pero incluso una función corta, imagina un código :

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

de mirar en este código, no se puede saber con claridad lo que es SomeValue.Podría ser incluso algunos #define o variable estática, pero si usted escribe

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

que tener claro que SomeValue es una variable miembro no estática de la misma clase.

Así que no solo ayuda a asegurar que el nombre de sus funciones o variables no entre en conflicto con otros nombres, sino que también hace que sea más fácil para otros leer y comprender el código fuente, escribiendo una auto documentación el código fuente a veces es muy importante también.

2

Otro caso, que ha llegado a las escenas después de C++ 11 está en lambdas donde se captura this.

Es posible que tenga algo como:

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

Aunque se genera el lambda dentro de una clase, sólo tendrá acceso a las variables locales mediante la captura de ellos (si su compilador C++ 14) o la captura de this . En el segundo caso, dentro del cuerpo de lambda, simplemente no está x, sino solo this->x.

Cuestiones relacionadas