HerpDerpington
HerpDerpington

Reputation: 4453

Defining destructor in derived class requires copy assignment operator

Take a look at this code example:

class A {
    A(const A&) = delete;
    A &operator=(const A&) = delete;    
protected:
    A() { }
    virtual ~A() { } // required for inheritance
    A(A&&) = default;
    A &operator=(A&&) = default;
};

struct B : public A {
    ~B() { } // Without the destructor the code compiles
};

int main(void)
{
    B b = B();
}

This code fails to compile, wtih g++-9 telling me that (in short)

line 15: error: use of deleted function 'B::B(const B&)'
line 9: note: 'B::B(const B&)' is implicitly deleted because the default definition would be ill-formed:
line 9: error: use of deleted function 'A::A(A&)'

See godbolt for the full error message.

Why does the compiler not use the move constructor/move assignment operator from class A? If I remove the destructor defined in struct B the code compiles. What is the reason for this behavior?

Upvotes: 1

Views: 200

Answers (1)

NathanOliver
NathanOliver

Reputation: 180630

When you do

~B() { }

in B you stop the compiler from generating a move constructor, so all it has is a copy constructor. Since A's is not acceptable it can't compile.

When you remove it, the compiler can create the move constructor automatically and you're good to go.


Note that this only applies to pre C++17. With C++17's guaranteed copy elision, B b = B(); becomes B b(); (if that would actually compile) so no copy or move happens.

Upvotes: 3

Related Questions