House& House::operator =(const House& source) { assert(m_rooms == -1); this->~House(); new(this) House(source); return *this; } It is not exception safe: If the copy constructor fails due to an exception, then the "this" object will be left in a destroyed state. It will probably be destroyed again when your object leaves scope. Destroying an object twice is undefined behavior.
Good point.
If you derive off of your "house" object, then this assignment operator will slice any of the derived parts...
Assignment operators aren't inherited, though, so if I derive a new class, say, Mansion, this would be illegal rather than slice off derived parts: Mansion x, y; x = y; Mansion would have to define its own assignment operator, if needed. (A client could hypothetically cast a Mansion to a House& and use its assignment operator, but no right-minded C++ programmer should resort to something that flagrant, and it would fail rather obviously if the object is used afterwards.)
In general, assignment operator should look like this (WARNING: untested code) House& House::operator =(const House& source) { House temp(source); Swap(temp); return *this; }
The Swap() function is a member function that has "No-Throw" specification. It swaps out the internals of the *this instance with the "temp" instance.
This makes sense, and would work for nearly all other types of classes.
But, is there any way to implement Swap so that it can swap out const
data members? I certainly can't do something like:
House* temp = new House(source);
memcpy(this, temp, sizeof(House);
// don't call original destructor
delete static_cast
Using this method, you are still writing your assignment operator in terms of your copy constructor, so you don't need to duplicate work. And this method is strongly exception safe; if the copy constructor throws, then the current object is unchanged.
Also, I would recommend that you either reconsider having the constant member variable, or use a vector<>.
Using a vector<T> won't work in this case, because the STL uses T::operator = in order to copy vector contents into new locations during memory reallocation. And there's no logical way to implement operator = when a const data member is present, which is the cause of this conversation. I could use std::list, since it doesn't do reallocation, but clients using this class in containers will most likely need random access iterators. Any other ideas? -Jonathan