Almost all c++ projects have classes with copy c-tor/copy operator/serialize method etc. Which usualy doing something with all members.
But sometimes developers forg
template<class T>
class SafeMember {
public:
T _; /* short name for convenience */
SafeMember(T const& obj) : _(obj) { }
};
Used like this:
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;
};
Now when you add a "SafeMember<int> age
" member and forget to update your copy-constructor, the compilation will helpfully fail.
And for a "no-op" hint, the developer would add an initializer like ":age(0)".
Note: this doesn't protect your operator=() or serialize() functions from bit-rot, only the constructors. Hopefully, though, this should be enough: once you see your omission from the constructors, you will probably remember to go through the other functions as well.
Add this functionality to your unit test. If your unit test covers serializaiton/deserialization (for example, by making sure deser(ser(x)) == x
), failure to add members to the serialization function would fail during unit testing. The same could work for copy ctors.
It's not as ideal as compile time errors, but if you have a good unit test framework in place and you make sure that you have proper coverage, then these errors of neglect would be harder to make.
I think the best way to avoid this problem is cut it at the root: Don't use custom copy operator/constructor.
This may not always be possible, but in most cases I really think it is...
It looks like there is no satisfying solution to your problem (Iraimbilanja solution is probably one of the best approaches, but still it's not perfect). I wonder if there are features in upcoming C++0x that will allow to solve this?