friendship and c++ methods inline friend

and - inline function c++



amigo Y método en línea, ¿cuál es el punto? (3)

Gramaticalmente hablando ...

La palabra clave friend todavía es necesaria para decirle al compilador que esta función no es miembro de una clase, EDITAR: sino una función no miembro que puede ver a los miembros privados de la clase.

Sin embargo, esto podría haberse implementado más limpiamente así:

/* friend */ inline bool operator ==(const MonitorObjectString& rhs) const { return fVal == rhs.fVal; }

(Por supuesto, fVal que fVal es de un tipo adecuado que se puede comparar sin afectar su consistencia).

Veo en un encabezado que no me escribí lo siguiente:

class MonitorObjectString: public MonitorObject { // some other declarations friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { return(lhs.fVal==rhs.fVal); }

No puedo entender por qué este método está declarado como amigo. Pensé que tendría sentido si la función se define en otro lugar y necesita acceder al miembro interno de la clase, pero este no es el caso aquí, ya que está en línea y ni siquiera necesita tener acceso a los miembros.

¿Qué piensas? ¿El "amigo" es inútil?


No son mutuamente excluyentes. "amigo" significa que la función no miembro puede acceder a los miembros privados de la clase. "en línea" significa que no hay invocación de invocación de función, el cuerpo de la función está duplicado (en ensamblaje) en cada sitio de llamada.


friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { return(lhs.fVal==rhs.fVal); }

se llama friend definition Definirá la función como una función no miembro del espacio de nombres que rodea la clase en la que aparece. En realidad, la línea allí es redundante: se declara implícitamente en línea si se trata de una definición de amigo. Algunos pros y contras de esto:

  • Hace que el operador no sea visible para la búsqueda normal. La única manera en que puede llamarlo es usando la búsqueda dependiente del argumento. Esto mantendrá el espacio de nombres libre de muchas declaraciones de operador visibles normalmente. Tenga en cuenta que esto también inhabilitará la posibilidad de llamarlo usando conversiones implícitas a MonitorObjectString (porque si ambos tipos de argumentos no coinciden al momento de buscar candidatos a los que llamar, la búsqueda dependiente del argumento no encontrará la función).
  • La búsqueda de nombres comienza en el ámbito de la clase en la que aparece la definición de amigo. Esto significa que no es necesario escribir largos nombres de letra u otros nombres. Simplemente refiéralos como lo harías en una función miembro normal de la clase.
  • Como es un amigo, la función ve las MonitorObjectString internas de MonitorObjectString . Pero eso no es ni bueno ni malo. Depende de la situación. Por ejemplo, si hay funciones getFVal() haciendo que la función friend no tenga sentido. Podría usar getFVal como ... bueno, entonces.

Me gustaba este estilo de definición de amigos de los operadores, porque tienen acceso directo a los miembros de la clase y aparecen dentro de la definición de clase, por lo que podría tener "todo con un solo vistazo". Recientemente, sin embargo, llegué a la conclusión de que no siempre es una buena idea. Si puede (y debe) implementar el operador utilizando puramente las funciones miembro públicas de la clase, debe convertirlo en un operador no amigo (y no miembro), definido en el mismo espacio de nombres de la clase. Se asegura de que si cambia alguna implementación, pero mantiene la interfaz de la clase igual, el operador seguirá funcionando y tendrá menos cambios en cascada, porque sabe que no puede acceder a los detalles de implementación.

Sin embargo , prefiero este estilo sobre los operadores miembros de escritura, porque las funciones del operador en el ámbito del espacio de nombres tienen las características adicionales de ser simétrico con sus argumentos: no tratan el lado izquierdo especial, porque ambos lados son solo argumentos normales y no argumentos del objeto que están obligados a *this . Si el lado izquierdo o el derecho es del tipo de su clase, el otro lado se puede convertir implícitamente, independientemente de si es izquierdo o derecho. Para las funciones que también se definen sin la sintaxis de definición de amigo (tradicionalmente, en el ámbito del espacio de nombres), tendrá la función de incluir selectivamente los encabezados que hacen que esos operadores estén disponibles o no.