Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prohibiting definition of a copy constructor in an inherited class

I want to make an abstract base class non-copyable and force any classes that derive from it to be non-copyable. The below code uses Boost's noncopyable as defined in noncopyable.hpp yet still allows D, the derived class, to define a copy constructor.

class noncopyable
{
    protected:
        noncopyable() {}
        ~noncopyable() {}
    private:  // emphasize the following members are private
        noncopyable( const noncopyable& );
        const noncopyable& operator=( const noncopyable& );
};

class D : noncopyable
{
    public:
        D() { }
        D(const D&) { }
};

int main()
{
    D a;
    D b(a);

    return 0;
}

This code compiles and runs (http://ideone.com/g4gGLm), when I expected it to throw a compile-time error about D's copy constructor. Maybe I have misinterpreted what this noncopyable class is meant to do. If so, is there any way to force derived classes to not define a copy constructor? (Answer can use C++11, but preferably not boost)

like image 969
steve9164 Avatar asked Mar 18 '13 11:03

steve9164


2 Answers

The reason this works is because D(const D&) calls the default constructor of the base class, not the copy constructor. (counter-intuitive at first, but it makes sense considering all constructors behave like this)

Since the copy constructor isn't called, a copy of the base object isn't created unless you explicitly ask for one:

D(const D& d) : noncopyable(d) { }

which would indeed result in an error. So in fact, your issue is a non-issue - there's no copying of noncopyable going on.

I'm not aware of any straight-forward way to force a derived class do disallow copying, nor would I recommend using one if there was.

like image 59
Luchian Grigore Avatar answered Oct 23 '22 19:10

Luchian Grigore


You need to delete the copy constructor of D. Right now you allow copy-construction of D's by not trying to copy-construct the base class. The following variants will not compile:

class E: noncopyable
{
};
E e, e2(e);

class F: noncopyable
{
public:
  F(const F &init): noncopyable(init)
  {}
};
like image 40
NonNumeric Avatar answered Oct 23 '22 19:10

NonNumeric