Sometimes there are cases where you don't want certain compiler generated functions to work. For instance, consider a class representing homes for sale:
class HomeForSale {...};
As every real estate agent will be quickly to point out, every property is unique and no two are exactly alike. Thus, it makes little sense to try to copy something unique:
HomeForSale h1;
HomeForSale h2;
HomeForSale h3(h1); // attempt to copy h1 using copy constructor - should not compile!
h1 = h1; // attemp to copy h2's value to h1 using assignment operator - should not compile!
Preventing such compilation can be tricky because they will be automatically generated by compiler if you dont generate them. The key to the solution is that all compiler
genearated functions are public. To prevent that, you have to manually declare them, but there is nothing that requires you to declare them public
!
Thus, to prevent copying you can declare copy constructor and copy assignment operator private
. By declaring them explicitly, you prevent compilers from generating their own version,
and by making the function private, you keep it from being called. Even though member and friend functions can still call them, not defining, implementing them can
make sure that if somebody inadvertently calls it, they will get an error at link-time.
This trick - declaring member functions private and deliberately not implementing them - is well established, as it is used to prevent copying in several classes in C++'s
iostreams library (ex: ios_base
, basic_ios
)
Here is an example:
class HomeForSale {
public:
...
private:
HomeForSale(const HomeForSale&); // declarations only
HomeForSale& operator=(const HomeForSale&);
};
Note:
- Names of the functions' parameters are omitted. It is a common convention since they will not be used.
- compilers will thwart client attempts to copy
HomeForSale
objects. Attempting to do so causes complains in linker.
It's also possible to move the link-time error earlier to compile time by declaring copy constructor and assignment operator in a base class specifically designed to prevent copying:
class Uncopyable {
protected:
Uncopyable() {} // allow construction and destruction
~Uncopyable() {} // of derived objects...
private:
Uncopyable(const Uncopyable&); // ...but prevent copying
Uncopyable& operator=(const Uncopyable&);
};
class HomeForSale: private Uncopyable { // class no longer declares
... // copy constructor or
}; // copy assignment operator
- Things to Remember
- To disallow functionality automatically provided by compilers, declare the corresponding member functions
private
and give no implementations. Using a base class likeUncopyable
is one way to do this.