I thought in theory the answer to this question was yes.
However, in practice, my compiler (VS2010) does not seem to complain in the following situation: I have an abstract base class providing some common interface (yet having no data members) and various sub and subsubclasses derived from it.
class Base
{
public:
Base() {}
virtual ~Base() {}
virtual void interfaceFunction1() = 0;
virtual void interfaceFunction2() = 0;
private:
Base(const Base&); // all derived classes should be uncopyable
Base& operator=(const Base&);
// no data members
};
My compiler found it unproblematic to even implement full copy constructors in sub- or subsubclasses.
How can I make sure that every class derived from Base is uncopyable?
edit: If I understand well, this is exactly what Scott Meyers explained in item 6 of Effective C++ (3rd edition, 2005) with his idea of the class Uncopyable
(only extended here to a full interface class). What is the difference that makes his idea work ? (I know that he inherits privately, but this should not pose a problem)
This should prevent the compiler from generating a copy constructor for derived classes which do not declare one explicitly. However, nothing prevents a derived class from explicitly declaring a copy constructor which will do something else than call the copy constructor of Base
.
There is no way to make sure derived classes are instantiable but not copyable.
Rather than declaring the copy constructor/operator as private declare them as deleted. Declaring copy constructor/operator as private is not the best solution to making the derived classes non-copyable. If you want the base class to be completely non-copyable then declare the copy constructor/operator as deleted as copy can still take place inside the member functions of Base as private members are accessible to that class's functions. You can use the C++11 feature of delete:
Base(const Base&) = delete; // copy constructor
Base& operator=(const Base&) = delete; // copy-assignment operator
But declaring copy constructor/operator as private is also right as long as you're aware that copy can still take place inside the member functions of Base.
In C++11 and later there is the option to declare a constructor deleted.
struct X {
X( const X& ) = delete;
};
Now, anything derived from X that rely on the copy-constructor will not compile.
This is most useful when you want to avoid problems because the compiler auto-generates constructors...