template<class T>
class SafeMember {
public:
T _; /* short name for convenience */
SafeMember(T const& obj) : _(obj) { }
};
usados como esto:
class Student {
public:
Student(string surname, Color hairColor)
: surname(surname)
, hairColor(hairColor) { }
Student(Student const& other)
: surname(other.surname)
, hairColor(other.hairColor) { }
Student& operator=(Student const& other) {
surname = other.surname;
hairColor = other.hairColor;
return *this;
}
string getSurname() const { return surname._; }
// The foo._ syntax is better than implicit conversion because
// it lets us call member functions, like substr in this example:
bool isSlavic() const {return surname._.substr(surname._.size()-2)=="ev";}
void dyeHair(Color newColor) { hairColor = newColor; }
private:
SafeMember<string> surname;
SafeMember<Color> hairColor;
};
Ahora, cuando se agrega un miembro "SafeMember<int> age
" y se olvide de actualizar su constructor de copia, la compilación será amablemente fallar.
Y para una sugerencia "no operativa", el desarrollador agregaría un inicializador como ": age (0)".
Nota: esto no protege las funciones operator =() o serialize() de bit-rot, solo los constructores. Con suerte, sin embargo, esto debería ser suficiente: una vez que vea su omisión de los constructores, probablemente recuerde pasar por las otras funciones también.
"no WRAPP todos los miembros camino". –
Bueno, SafeMember hace que sea lo suficientemente fácil para envolverlos. Creo que OP quiere evitar envolverlos _manualmente_. –
Lo sentimos, pero funciona con la nueva variable de miembro. Tengo un recordatorio solo para el constructor predeterminado. – bayda