uso una son sirve setters que poo para metodos los incluya getters encapsulamiento ejemplo crear con como clase c++ getter

una - set y get c++



¿Qué debería devolver un getter de C++? (5)

¿Cuál es la mejor práctica para un método getter de C ++ que se supone que devuelve un tipo no trivial, pero un miembro que es de tipo type o struct?

  1. Devuelve por valor, como MyType MyClass::getMyType() { return mMyType; } MyType MyClass::getMyType() { return mMyType; }
  2. Return by const reference: const MyType& MyClass::getMyType() { return mMyType; } const MyType& MyClass::getMyType() { return mMyType; }
  3. Devolver por dirección: MyType* MyClass::getMyType() { return &mMyType; } MyType* MyClass::getMyType() { return &mMyType; }

dónde

class MyType { /* ... */ }; class MyClass { private: MyType mMyType; }

Me preocupo específicamente por los siguientes usos de este método. ¿Puede explicar detalladamente cómo esto podría afectar la copia del objeto, y el peligro de referencias colgantes y punteros desenfrenados si function() quiere guardarlo para un uso posterior?

MyType* savedPointer; SomeType function(MyType* pointer) { savedPointer = pointer; };

a. válido para 1. y 2.

{ MyType t = myClass.getMyType(); function(&t); } // is savedPointer still valid here?

segundo. válido para 1. y 2.

{ const MyType& t = myClass.getMyType(); function(&t); } // is savedPointer still valid here?

do. válido para 1. y 2.

{ MyType& t = myClass.getMyType(); function(&t); } // is savedPointer still valid here?

re. válido para 3.

{ MyType* t = myClass.getMyType(); function(t); } // is savedPointer still valid here?

donde myClass es un objeto de tipo MyClass .


Devuelve por valor, como MyType MyClass::getMyType() { return mMyType; } MyType MyClass::getMyType() { return mMyType; } debe evitarse ya que copiará el contenido de su objeto. No veo la ganancia que podrías tener pero veo los inconvenientes en el rendimiento.

Return by const reference: const MyType& MyClass::getMyType() { return mMyType; } const MyType& MyClass::getMyType() { return mMyType; } es más generalmente usado de esta manera:

const MyType& MyClass::getMyType() const { return mMyType; } MyType& MyClass::getMyType() { return mMyType; }

Siempre proporcione la versión const. La versión no const es opcional ya que significa que alguien puede modificar sus datos. Es lo que te animo a usar.

Devolver por dirección: MyType* MyClass::getMyType() { return &mMyType; } MyType* MyClass::getMyType() { return &mMyType; } se usa principalmente cuando los datos están opcionalmente allí. A menudo debe verificarse antes de ser utilizado.

Ahora, en su caso de uso, recomendaría encarecidamente que no se guarde un puntero para más que un alcance. A menudo puedo conducir a problemas de propiedad. Tengo que hacerlo, eche un vistazo a shared_ptr .

Para sus ejemplos, hay dos casos:

a. savedPointer ya no será válido después del corchete de cierre.

b, c, y d. savedPointer es válido después del corchete de cierre, pero ten cuidado de que no sobreviva a myClass .


En general, debería preferir el retorno por valor, a menos que explícitamente quiera garantizar que la referencia designará un miembro (lo que expone parte de su implementación, pero es deseable en casos como std::vector<>::operator[] ). Devolver una referencia evita cambios posteriores en la clase, ya que significa que no puede devolver un valor calculado. (Esto es especialmente importante si la clase está diseñada para ser una clase base, ya que devolver una referencia crea esta restricción para todas las clases derivadas).

La única vez que debe regresar con el puntero es si está involucrada una búsqueda o algo, que puede regresar al tener que devolver un puntero nulo.

Devolver una referencia a const puede ser una optimización válida, si el generador de perfiles indica problemas de rendimiento aquí, y el sitio de llamadas también puede tratar con una referencia constante (sin modificación del valor devuelto, sin problemas con el tiempo de vida del objeto). Por supuesto, debe sopesarse contra las restricciones adicionales en la implementación, pero en algunos casos, está justificado.


Puede proporcionar tanto versiones const como no const:

MyType & MyClass::getMyType() { return mMyType; } MyType const & MyClass::getMyType() const { return mMyType; }

No proporcionaría una versión de puntero, ya que eso implica que el valor de retorno podría ser el puntero nulo, que nunca puede ser en este caso.

El verdadero punto, sin embargo, es que básicamente le está dando a la persona que llama el acceso directo al objeto interno. Si esta es su intención, entonces también puede hacer público el miembro de datos. Si no es así, entonces tendrá que trabajar más para ocultar el objeto.

Una opción es conservar el MyType const & accessor MyType const & , pero proporcionar más medios indirectos para modificar el objeto interno ( setMyType(…) o algo más adaptado a la semántica que está tratando de expresar en el nivel de la clase contenedora).


Siempre devolvería una referencia constante. Si necesita modificar el valor que está devolviendo, solo use una función setter.


a) MyType t = creará una copia del objeto para 1 y 2. El puntero guardado no será válido una vez que t esté fuera del alcance.

b) El puntero guardado será válido para el caso que devuelve una referencia, pero no válido para el caso que devuelve un objeto. Para la referencia, la duración del puntero sería la misma que myClass. Por supuesto, t en un const ref sería una configuración * no en * y, por lo tanto, no se lanzaría en su llamada a la function(MyType*) .

c) Igual que b, aunque el código no es válido para 2 porque no puede const MyType& un const MyType& a un MyType& . En general, esto sería una mala práctica y la forma const sería más aceptable.

d) savedPointer tendrá la misma duración que myClass.

En general, me inclino por devolver una referencia o una referencia constante, dependiendo de lo que espera poder hacer con el valor de retorno. Si devuelve una referencia (no const), puede hacer cosas como: myClass.getMyType() = ... , mientras que si devuelve una referencia const, el objeto es de solo lectura.