Can a derived class be made uncopyable by declaring copy constructor/operator private in base class?
Asked Answered
S

3

7

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)

Scraper answered 8/7, 2015 at 9:57 Comment(8)
May be add a dummy data member.Inane
Did you test other compilers? Also presenting a derived class would be nice ;) (actually more of something like a compilable example.)Economy
What's the use of a pure function not marked virtual?Commonwealth
@MarcoA. The only purpose I can think of is triggering a compilation error. I would chalk this up to "oversimplified for SO."Hyaena
Please post an MCVE. This should work.Hotel
@MarcoA sorry, editedScraper
@Angew indeed, editedScraper
derived class was nothing special, an implementation of the interface functions and some data members, it would be too extensive to post here, especially since Angew already pointed to the real reason why I could implement copy constructors.Scraper
H
4

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.

Hyaena answered 8/7, 2015 at 10:6 Comment(2)
Could it be a solution to make Base() private ? (but then I would have to resort to static factory methods, which sounds like a lot of hassle just to make these classes uncopyable)Scraper
@TG_ No, that wouldn't work. If you leave all Base constructors private, the derived class will not be able to initialise itself at all (not by copy, not by default, not any other way). If you leave any Base constructor accessible, the derived class can use that in its own copy ctor.Hyaena
R
1

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.

Romalda answered 8/7, 2015 at 12:52 Comment(3)
making them private and declaring as deleted has the same effectWomack
@BЈовић Not necessarily, making them private does not assure that objects of that type are not copyable. If we declare them as deleted then no copy can ever take place. Item 11 of Effective Modern C++ states that code that's in member and friend functions will fail to compile if it tries to use a deleted member function. Declaring them as private means that code inside member functions and friends of that particular class can use them and linking will fail due to missing function definition.Romalda
A default copy-constructor will create new base object, and not try to copy it. So, this approach will not work, if derived class uses default copy constructor, and the derived class will be copyable, whereas the base isn't.Womack
M
0

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

Millipede answered 18/10, 2018 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.