Possible Duplicate:
What's the most reliable way to prohibit a copy constructor in C++?
Suppose I want to make a class non-copyable and want to prohibit copy constructor and assignment operator. I make them private and leave unimplemented:
class Class {
//useful stuff, then
private:
Class( const Class& ); //not implemented anywhere
void operator=( const Class& ); //not implemented anywhere
};
this way if any of them is accidentially called from within friends or the same class I get a link-time error.
Now what if a user implements them? I mean there's no implementation, so anyone can add his own:
Class::Class( const Class& )
{
//whatever they want
}
Of course I could have created my own implementation and add an assertion there, but that would delay unintended calls detection until the program is run.
Is there a way to prevent implementing such method by a user and still have compile-time detection of unintended calls to them?
Solution and Sample CodeEdit class NonCopyable { public: NonCopyable (const NonCopyable &) = delete; NonCopyable & operator = (const NonCopyable &) = delete; protected: NonCopyable () = default; ~NonCopyable () = default; /// Protected non-virtual destructor }; class CantCopy : private NonCopyable {};
Boost::noncopyable prevents the classes methods from accidentally using the private copy constructor.
Sometimes it's necessary to prohibit a copy constructor in a C++ class so that class becomes "non-copyable". Of course, operator= should be prohibited at the same time.
A cleaner solution: create a class where the default copy constructor and/or default copy assignment operator are deleted. Derive all your classes or the base class of the class hierarchies from this special class. Copy construction and/or copy assignment will now be disabled for all these classes automatically.
In C++0x there is the new delete
keyword, that does just this
What's the most reliable way to prohibit a copy constructor in C++?
There is no problem here.
The client can provide implementations of those methods a much as they like, but the compiler will still complain because they're private.
Now, can you prevent someone hacking your header file, changing them to public and linking their own implementations?
Yes, provide your own implementations that throw exceptions, your hypothetical hacker will get a link error when they try to build.
In the normal course of events this doesn't slow anything down, as the compiler will never try to call those methods, and code that tries will be told
. . . cannot access private member declared in class . . .
In the case some "clever" gobshite tries, then yes the assertions will be delayed, but mate, that's not your problem, you can't protect every idiot in the world from shooting them selves in the foot.
+1 BTW, interesting question :)
. . . as pointed out by Xeo, the above only works for non templated classes
Well the solution is like it is usually done in practice - use special non-copyable base class (e.g. boost::noncopyable or your own class). E.g.
class noncopyable
{
// private
noncopyable( const noncopyable& ); // not implemented
noncopyable& operator=( const noncopyable& ); // not implemented
// no friends, etc
};
Then somewhere
class A: noncopyable
{
// Anything ...
};
Obviously since there is no friends of noncopyable
its copy constuctor and assignment operator is always private for everyone so it doesn't matter if it is implemented or not (compiler denies using them anyway).
A bit of a non-answer to the question, but perhaps a different approach, depending a lot on what you're trying to achieve.
On the face of it, it sounds like you want compile time detection whilst you're developing the library in order to speed up detection and avoid relying on runtime testing identifying the issue.
If this is the case, can you not solve your problem by having two builds?
Build One (internal build): which builds the library and doesn't link in the copy constructor functions.
Build Two (client build): which links in the copy construction logic with asserts (from a different implementation file), so that there's runtime protection & the client can't provide their own implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With