Can a derived class be made uncopyable by declarin

2019-04-26 15:14发布

问题:

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)

回答1:

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.



回答2:

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.



回答3:

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...