Is it meaningful\suitable to mark the derived class as movable while the base class is non-moveable?

Viewed 99

Is it meaningful\suitable to mark the derived class as movable while the base class is non-moveable?

I know this kind of inconsistency is legal in C++, but is it meaningful\suitable in practise?

In general, should I sedulously keep such consistency?

What about this case:when I intend to mark the derivd class as non-moveable and non-copyable, should I mark the base class as non-moveable and non-copyable, too?

I did several tests to make it clear.

Here is the first example. Since the base class is non-copyable and non-moveable, the derived class is non-moveable in fact through it has a move constructor, which is in my expectation. Tips: the code snippet below does not compile.

#include <memory>
#include <string>
#include <iostream>

class Base {
public:
    Base(){}
    Base(const Base&) = delete;
    Base(Base&&)      = delete;
    Base& operator=(const Base&) = delete;
    Base& operator=(Base&&) = delete;
};

class Derived:public Base
{
public:
    Derived(){}
    Derived(const Derived&) = default;
    Derived(Derived&&)      = default;
    Derived& operator=(const Derived&) = default;
    Derived& operator=(Derived&&) = default;
};

int main()
{
    Derived derived;

    Derived derived1{std::move(derived)};
}

Here is the second example. The base class is copyable and non-moveable, but the derived class is moveable in fact since it will invoke the copy constructor of the base class instead of the move constuctor of base class when the move constructor of the derived class is called, which is also in my expectation.Tips: the code snippet below works well.

#include <memory>
#include <string>
#include <iostream>

class Base {
public:
    Base(){}
    Base(const Base&) = default;
    Base(Base&&)      = delete;
    Base& operator=(const Base&) = default;
    Base& operator=(Base&&) = delete;
};

class Derived:public Base
{
public:
    Derived(){}
    Derived(const Derived&) = default;
    Derived(Derived&&)      = default;
    Derived& operator=(const Derived&) = default;
    Derived& operator=(Derived&&) = default;
};

int main()
{
    Derived derived;

    Derived derived1{std::move(derived)};
}

UPDATED:

Thanks to @Nightlord, he found that the code snippet above does not compile with Clang, which is really out of my expectation.

1 Answers

I know this kind of inconsistency is legal in C++, but is it meaningful in practise?

In general, should I sedulously keep such consistency?

Yes, I think you should keep the consistency. To make a derived class movable while the base class is not, the base class cannot hold any data member, otherwise, the movement is not completed.

In the case your class does not hold any data member, you might be using it as an interface. Moving constructor does not work with such a case since the client only recognizes the interface (the base class) rather than the concrete class (the derived class).

Related