Правило нуля против деструкторов базового класса

У меня есть базовый класс Base и производный класс D, и я хотел бы, чтобы конструктор перемещения и оператор присваивания перемещения автоматически генерировались компилятором для меня. Следуя правилу нуля, я оставляю все управление памятью компилятору и использую только классы уровня 2 (без необработанных указателей, массивов и т. Д.):

#include <iostream>

class Base{
  public:
    Base(): a_(42) {}
    virtual void show() { std::cout << "Base " << a_ << std::endl; }

  private:
    int a_;
};

class D : Base {
  public:
    D(): b_(666) {}
    void show() { std::cout << "D " << b_ << std::endl; }

  private:
    int b_;
};

int main() {
  Base b;
  b.show();
  D d;
  d.show();
  return 0;
}

Это должно быть так, верно?

Введите основные рекомендации C++:

Деструктор базового класса должен быть либо общедоступным и виртуальным, либо защищенным и не виртуальным.

Ах, я думаю, мне придется добавить деструктор Base, Но это покончит с автоматически генерируемыми функциями перемещения!

Какой тут чистый выход?

2 ответа

Решение

Вы можете = default все, что вы хотели бы сгенерировать компилятором. Смотрите (внизу): http://en.cppreference.com/w/cpp/language/rule_of_three

В вашем случае это может выглядеть примерно так:

class Base{
  public:
    Base(): a_(42) {}
    Base(const Base&) = default;
    Base(Base&&) = default;
    Base& operator=(const Base&) = default;
    Base& operator=(Base&&) = default;
    virtual ~Base() = default;

    virtual void show() { std::cout << "Base " << a_ << std::endl; }

  private:
    int a_;
};

Вы можете создать один раз, как класс

struct VirtualBase
{
      virtual ~VirtualBase() = default;
      VirtualBase() = default;
      VirtualBase(const VirtualBase&) = default;
      VirtualBase(VirtualBase&&) = default;
      VirtualBase& operator = (const VirtualBase&) = default;
      VirtualBase& operator = (VirtualBase&&) = default;
};

А затем следуйте правилу нуля:

class Base : VirtualBase
{
public:
    Base(): a_(42) {}
    virtual void show() { std::cout << "Base " << a_ << std::endl; }

  private:
    int a_;
};
Другие вопросы по тегам