Почему C4265 Visual C ++ предупреждение (виртуальная функция-член и нет виртуального деструктора) отключено по умолчанию? - PullRequest
1 голос
/ 08 ноября 2011

Visual C ++ может выдавать C4265 предупреждение , когда у класса есть хотя бы одна виртуальная функция-член и нет виртуального деструктора.

Очевидно, есть предупреждение для обнаружения случаев, когда объект производного класса delete d через указатель на базовый класс и в базовом классе нет виртуального деструктора. Такая ситуация приводит к неопределенному поведению. Кстати, я только что нашел пример этой ситуации в довольно большой кодовой базе именно благодаря включению C4265 в Visual C ++.

И это предупреждение по умолчанию отключено.

Почему? Что произойдет, если я включу его и добавлю виртуальный деструктор в каждый класс, из которого выдается предупреждение?

Ответы [ 4 ]

3 голосов
/ 08 ноября 2011

Я предполагаю, что иногда вам не нужен виртуальный деструктор, даже если у вас есть виртуальные функции (и, следовательно, подумайте о наследовании от него).

Вам нужен виртуальный деструктор, если вы выделяете память в производном классе и хотите освободить ее при уничтожении объекта, но это не всегда так.

Виртуальный деструктор также означает, что вы должны реализовать конструктор копирования и оператор присваивания (правило трех), которые также не нужны, если члены вашего класса являются просто типами POD.

Итак, подведем итог: вы получите это предупреждение даже для классов, где вам не нужен виртуальный деструктор, так зачем его иметь?

2 голосов
/ 08 ноября 2011

В ссылке для документации по этому предупреждению объясняется обоснование Microsoft. If a warning is off by default, most users would not want to see it.

1 голос
/ 21 января 2012

Я думаю, что много предупреждений могут быть среди тех, кто использует шаблоны Mixin.

WikiPedia: В объектно-ориентированных языках программирования миксин - это класс, который предоставляет определенные функциональные возможности, которые наследуются или просто используются подклассом, но не предназначены для создания экземпляров (генерации объектов этого класса). Миксины являются синонимами абстрактных базовых классов. Наследование от миксина - это не форма специализации, а скорее средство сбора функциональности. Класс или объект могут «наследовать» большую часть или всю свою функциональность от одного или нескольких миксинов, поэтому миксины можно рассматривать как механизм множественного наследования.

Пример:

Смешанный класс

template <typename T> struct AddNoEq {
  virtual bool operator==(const T &cmp) const = 0;
  bool operator!=(const T &cmp) const {
    return !static_cast<const T*>(this)->operator== (cmp);
  }
};

Использование:

struct Complex : public AddNoEq<Complex> {
  Complex(int re, int im): re_(re), im_(im) { }

  virtual bool operator==(const Complex& cmp) const {
      return cmp.re_ == this->re_ && cmp.im_ == this->im_;
  }
  // ...
private:
  int re_, im_;
};

int main()
{
  Complex a(1, 2), b(2, 3);

    if (a != b)
      std::cout << "OK!" << std::endl;

    return 0;
}
0 голосов
/ 08 ноября 2011

Microsoft иногда предупреждает о «устаревших функциях», которые не помечены как таковые комитетом по спецификации, или об определенной «хорошей или плохой практике».

Наличие не виртуального деструктора в объекте, имеющем виртуальные методы, представляет потенциальный риск, если этот объект спроектирован так, чтобы оставить его в полиморфной ООП-среде (где delete pObject должен также правильно delete pDerived, даже если смотреть с pObject ). Но это только одна из опор парадигмы C ++ ... поэтому такое предупреждение может быть бессмысленным:

Также p->dosomething() не вызывает Derived::dosomething, если dosomething не является виртуальным, но для этого не генерируется предупреждение.

Для меня delete p, делая вид, что P::~P() приводит к вызову D::~D(), не является особым случаем и не должно заслуживать предупреждения.

Но, к сожалению, ООП была первой парадигмой, которую изначально поддерживала C ++, и парадигмой, на которую ссылается большинство программистов, распространяющих книги и учителей, поэтому они применили лучшую практику «не извлекайте, если деструктор не виртуален» К сожалению, сообщается также Скотом Мейерсом в его «Эффективном C ++», что делает его «популярным» и постоянно упоминается также, если нет технических причин для его продолжения существования.

Сегодня это не то же самое, что и большинство «не делай этого, не делай этого» (включая знаменитое «Дойкстра, считающееся вредным»), в котором много нового акцентируется на структурированном программировании, но также много нелепые способы раскручиваться, просто чтобы избежать этого ... Ха ... У Miscrosoft нет предупреждения о применении goto ... Может быть, Мейерс более влиятельный, чем Джикстра был ??)

Единственная хорошая практика - «не делай НИЧЕГО, если не знаешь, что делаешь!». Ничто не запрещает принимать предложения, но «лучшая практика» не является «всегда хорошей практикой» (иначе она не будет «лучшей»: просто будет «только»), и компилятор (как формальный инструмент) не должен предупреждать о субъективном чувства.

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