c++ - object oriented programming concepts pdf
Campo de referencia Const como propiedad de solo lectura en la clase C++ (4)
¿Este código cumple con las buenas prácticas?
No realmente, ya que introduce una complejidad innecesaria y sobrecarga de espacio.
Además, no podría realizar comprobaciones y / o aserciones en tiempo de ejecución, independientemente del valor al que se acceda.
Además, ¿qué pasa con la vida y la semántica?
Intente asignar un check
en su código a otro y vea qué sucede. La asignación está mal formada porque la clase no es asignable. Debe proporcionar una copia y mover el constructor para hacerse cargo de la referencia, de modo que no se refiera al miembro de datos del objeto anterior.
Utilice mejor _x
directamente y tenga una función getter en línea directa.
¿Es bueno usar un campo de referencia de const como un getter de solo lectura en las clases de C ++?
Quiero decir, ¿este código cumple con las buenas prácticas?
class check{
private:
int _x;
public:
const int& x = _x;
void setX(int v){
_x = v;
}
};
Funciona de forma muy parecida a las propiedades de C #, IMHO y un código de uso de clase muy sencillo y limpio:
check s;
int i;
std::cin >> i;
s.setX(i);
std::cout << s.x << ''/n'';
s.setX(7);
// s.x = i; // Error
std::cout<<s.x<<''/n'';
Cuando C # compila una propiedad, se compila en una función get y set.
Aquí hay un código C # que demuestra este hecho:
using System;
namespace Reflect
{
class Program
{
class X
{
public int Prop { get; set; }
}
static void Main(string[] args)
{
var type = typeof(X);
foreach (var method in type.GetMethods())
{
Console.WriteLine(method.Name);
}
Console.ReadKey();
}
}
}
Su salida debe ser:
get_Prop
set_Prop
ToString
Equals
GetHashCode
GetType
get_Prop
es la función que implementa el getter. set_Prop
es la función que implementa el setter.
Entonces, incluso si lo que estás haciendo parece similar, no es lo mismo en absoluto.
Francamente, casi todo lo que podrías hacer para tratar de emular la ''sintaxis de propiedades'' en C ++ caerá de una forma u otra. La mayoría de las soluciones le costarán memoria o tendrá alguna limitación que lo hace más engorroso que útil.
Solo aprende a vivir con captadores y setters. Getters y setters son una buena práctica . Son cortos, son simples, son flexibles, generalmente son buenos candidatos para la alineación, todos entienden lo que hacen, etc.
En general, no es una buena práctica.
Imho, y muy fácil y limpio en el código de uso de clase.
¿Por qué debería ser más claro y fácil?
- Usted introduce otro miembro variable (sobrecarga inútil). (En general, la referencia se implementará como un puntero de miembro adicional).
- Hace que el código sea más difícil de mantener. En realidad estás creando dependencias entre miembros variables.
- Hace problema en la asignación y en las operaciones de copia. ¿Cómo se supone que funciona la operación de copia?
El enfoque "clásico" es más claro para mí, por ejemplo:
class Foo {
public:
void set_num(int value) noexcept { m_num = value; }
int get_num() const noexcept { return m_num; }
void set_string(std::string value) noexcept {
m_str = std::move(value);
}
const std::string& get_string() const noexcept {
return m_str;
}
private:
int m_num;
std::string m_str;
};
Desde el punto de vista de las actuaciones, este enfoque debería ser preferido.
- Complejidad de tiempo: la llamada
get_variable
en una función en línea no introduce más sobrecarga que su "enfoque de referencia". Además, es altamente optimizable por el compilador (debido a que el código es sencillo). - Complejidad de espacio: no introduce datos adicionales.
Lo que propones es en general una mala idea:
- No puede implementar la propiedad haciendo ningún procesamiento (por ejemplo, con un captador puede almacenar coordenadas usando [x, y] y luego decidir cambiar la implementación para usar [ángulo, radio] mientras se mantiene la misma interfaz pública).
- El uso de una variable miembro de const implica una sobrecarga de espacio y no le brinda ninguna ventaja de rendimiento en comparación con un captador en línea.
- No es idiomático.
- Una vez que haya publicado su clase, y otras personas comiencen a usarla, quedará atrapado en ella: es demasiado tarde para cambiarla y usar un método.
Si su intención con las propiedades es hacer que el código sea más conciso, no tiene que usar las palabras "obtener" y "establecer" en sus nombres de funciones; Esa es una práctica pasada de moda. Puede usar el nombre real de la "propiedad" como el nombre de la función, y puede sobrecargar al captador y al configurador:
class Cheque {
public:
int x() const {
return x_;
}
Cheque & x(int newX) {
x_ = newX;
return *this;
}
private:
int x_;
}
// Usage:
// int amt = myCheque.x(1234);
// Cheque c = Cheque().x(123);
Devolver *this
como en el código anterior le permite utilizar el encadenamiento de métodos ; una forma de implementar el lenguaje de interfaz fluida .