Отключение предупреждений GCC при использовании класса «Uncopyable» - PullRequest
1 голос
/ 27 декабря 2008

У меня есть несколько классов, которые я не хочу копировать, некоторые из этих классов имеют члены-указатели. Чтобы сделать эти классы не копируемыми, я в частном порядке наследую следующий шаблон класса:

template <class T>
class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    T & operator=(const T&);
};

Который я использовал так:

class Entity : private Uncopyable<Entity> { }

Это прекрасно работает, однако, когда я компилирую с -Weffc ++, я все равно получаю следующее предупреждение:

class Entity has pointer data members
but does not override Entity(const Entity&)
or operator=(const Entity&)

Почему он до сих пор дает мне это предупреждение?

1 Ответ

9 голосов
/ 27 декабря 2008

C ++ говорит

Поскольку оператор присваивания копии неявно объявлено для класса, если не объявлено пользователем, оператор присваивания копии базового класса всегда скрыт оператором копирования копии производного класса (13.5.3). Объявление использования (7.3.3), которое приносит из базового класса оператор присваивания с типом параметра, который может быть типом присваивания при копировании оператор для производного класса не считается явным объявлением оператора копирования и не подавляет неявное объявление оператора копирования-присвоения производного класса; оператор, введенный объявлением использования, скрыт неявно объявленным оператором копирования-назначения в производный класс.

Ошибка в коде заключается в том, что ваш базовый класс объявляет operator= для принятия ссылки на тип производного класса. Это не помешает неявному публичному объявлению оператора = для базы. Таким образом, ваш производный класс и ваш базовый класс по-прежнему можно назначать. Попробуйте изменить свой класс без возможности копирования на шаблон, которого должно быть достаточно:

class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    Uncopyable & operator=(const Uncopyable&);
};

Еще одна вещь, которую я только что изобразил в этом коде: не делайте деструктор Uncopyable виртуальным. Причина в том, что никто (кроме самого производного класса) не может вызывать delete для указателя на Uncopyable (потому что 1: деструктор защищен, 2: вы получаете приватно). Поэтому Uncopyable не стоит делать деструктор производного класса неявно виртуальным. Если производный класс должен иметь виртуальный деструктор, поместите вместо него виртуальный и оставьте деструктор Uncopyables не виртуальным.

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