2009-03-17 18 views
9

Casi todos los proyectos C++ tienen clases con copy c-tor/copy operator/serialize method etc. Lo que habitualmente hace algo con todos los miembros.agregar nuevo miembro para copiar c-tor/copy o-tor/serialization reminder

Pero a veces los desarrolladores olvidan agregar un nuevo miembro a estas funciones.
¿Conoces alguna forma fácil, no englobar a todos los miembros, que les recordará a los desarrolladores que hagan algo o escriban noop (memeber_name_) en estas funciones.

Intenté inventar algo, pero obtuve una falla.

PD: las pruebas unitarias podrían evitar este problema, pero quiero algo de tiempo de compilación.

Respuesta

1
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.

+0

"no WRAPP todos los miembros camino". –

+0

Bueno, SafeMember hace que sea lo suficientemente fácil para envolverlos. Creo que OP quiere evitar envolverlos _manualmente_. –

+0

Lo sentimos, pero funciona con la nueva variable de miembro. Tengo un recordatorio solo para el constructor predeterminado. – bayda

0

Parece que no hay una solución satisfactoria para su problema (la solución Iraimbilanja es probablemente uno de los mejores enfoques, pero aún así no es perfecto). Me pregunto si hay características en el próximo C++ 0x que permitirán resolver esto?

+0

Continúo intentando descubrir una solución aceptable :) Será aceptable si C++ 0x tendrá algunas herramientas para resolver el problema. Comprobaré el borrador de C++ 0x. – bayda

+0

Tal vez el compilador podría verificarlo y emitir una advertencia de que algún miembro no está copiado ... pero ¿cómo diría usted que no le importa un miembro ... –

1

Agregue esta funcionalidad a su unidad de prueba. Si su prueba unitaria cubre la serialización/deserialización (por ejemplo, asegurándose de deser(ser(x)) == x), la falla al agregar miembros a la función de serialización fallaría durante la prueba unitaria. Lo mismo podría funcionar para copiadores.

No es tan ideal como los errores de tiempo de compilación, pero si tiene un buen marco de prueba de unidad en su lugar y se asegura de que tenga una cobertura adecuada, entonces estos errores de negligencia serían más difíciles de hacer.

+1

Gracias por su respuesta. En general: pruebas unitarias: algo bueno, y pensé en el control con pruebas unitarias. Pero podemos olvidar agregar miembro al operador == y assert (deserialize (serialize (x)) == x) o 'y = x; assert (y == x); va a estar bien si olvidamos agregar miembro en algunas de las funciones utilizadas. – bayda

0

Creo que la mejor manera de evitar este problema es cortarlo en la raíz: No utilice el operador/constructor de copia personalizada.

Esto no siempre puede ser posible, pero en la mayoría de los casos realmente creo que es ...

Cuestiones relacionadas