Проблема с наследованием операторов и cpp базовыми рекомендациями c .128 - PullRequest
1 голос
/ 13 февраля 2020

У меня следующий код (здесь я удалил некоторый код, который не важен):

class State {
public:

  virtual void enter() = 0;
  virtual void update() = 0;
  virtual void exit() = 0;
};

class SimpleState : public State {
public:

  SimpleState() = default;
  SimpleState(const SimpleState&) = default;
  SimpleState(SimpleState&&) = default;
  virtual ~SimpleState() = default;

public:

  void enter() override;
  void update() override;
  void exit() override;

public:

  SimpleState& operator=(const SimpleState&) = default;
  SimpleState& operator=(SimpleState&&) = default;
};

Я добавил операторы по умолчанию, чтобы устранить предупреждение, так как я определил деструктор и нужно также определить другие вещи (правило 5, если я помню).

Если я создаю его с помощью Visual Studio 2019, включив основные рекомендации cpp, я получаю следующие предупреждения:

SimpleState.hpp: warning C26456: Operator 'SimpleState::operator=' hides a non-virtual operator 'State::operator=' (c.128).
SimpleState.hpp: warning C26456: Operator 'SimpleState::operator=' hides a non-virtual operator 'State::operator=' (c.128).

Я хочу избавиться от него, поэтому я изменил код следующим образом:

class State {
public:

  virtual void enter() = 0;
  virtual void update() = 0;
  virtual void exit() = 0;

public:

  virtual State& operator=(const State&) = 0;
  virtual State& operator=(State&&) = 0;
};

class SimpleState : public State {
public:

  SimpleState() = default;
  SimpleState(const SimpleState&) = default;
  SimpleState(SimpleState&&) = default;
  virtual ~SimpleState() = default;

public:

  void enter() override;
  void update() override;
  void exit() override;

public:

  SimpleState& operator=(const SimpleState&) override = default;
  SimpleState& operator=(SimpleState&&) override = default;
};

Но в этом случае я получаю следующие ошибки:

SimpleState.hpp: error C3668: 'SimpleState::operator =': method with override specifier 'override' did not override any base class methods
SimpleState.hpp: error C3668: 'SimpleState::operator =': method with override specifier 'override' did not override any base class methods

Что Я делаю неправильно, и как я могу удалить предупреждение?

Ответы [ 2 ]

2 голосов
/ 13 февраля 2020

Я подозреваю, что предупреждение C26456 в этом случае является ошибкой, см. Также https://developercommunityapi.westus.cloudapp.azure.com/content/problem/617702/c26456-false-positive-with-operator-in-derived-cla.html и https://developercommunity.visualstudio.com/content/problem/228085/c-core-check-false-positive-c26434.html.

Ссылочный пункт основного руководства C .128 применяется только к виртуальным функциям-членам, но operator= не является виртуальным в вашем базовом классе и не имеет той же сигнатуры, что и в производном классе, поэтому нет причин для этого apply.


Убедитесь, что вы действительно хотите объявление деструктора в SimpleState. В базовом классе State есть виртуальные функции, которые, по-видимому, указывают на то, что вы хотите полиморфно использовать State и что объекты могут быть уничтожены с помощью указателей State, а не указателей SimpleState. В этом случае для State должен быть объявлен виртуальный деструктор, а не SimpleState.

Если вы объявите виртуальный деструктор в State, вам не нужно будет объявлять никакой деструктор в SimpleState , который унаследует виртуальный деструктор от State. Тогда SimpleState может следовать правилу нуля, и ему не понадобятся какие-либо операторы назначения копирования / перемещения и объявленные конструкторы копирования / перемещения, что является предпочтительным способом.

0 голосов
/ 13 февраля 2020

По сути, для переопределения любого метода подпись переопределяющего метода должна совпадать с исходной сигнатурой метода. В вашем случае, однако, подпись отличается SimpleState& operator=(const SimpleState&) против State& operator=(const State&). Поэтому вы не переопределяете исходный метод, а объявляете метод переопределением, что приводит к ошибке.

...