为什么 C4265 Visual C++ 警告(虚拟成员函数和无虚拟析构函数)默认关闭?

问题描述 投票:0回答:4
当类至少有一个虚拟成员函数且没有虚拟析构函数时,

Visual C++ 会发出 C4265 警告

显然,警告是为了检测派生类对象通过指向基类的指针进行

delete
d 并且基类中没有虚拟析构函数的情况。这种情况会产生未定义的行为。顺便说一句,我刚刚通过在 Visual C++ 中启用 C4265,在相当大的代码库中找到了这种情况的示例。

默认情况下此警告处于关闭状态。

为什么?如果我启用它并向发出警告的每个类添加虚拟析构函数,会发生什么?

c++ visual-c++ destructor compiler-warnings
4个回答
3
投票

我的猜测是,有时您不需要虚拟析构函数,即使您确实有虚拟函数(因此考虑从它继承)。

如果您在派生类中分配内存并需要在对象销毁时释放它,则需要虚拟析构函数,但情况并非总是如此。

虚拟析构函数还意味着您应该实现复制构造函数和赋值运算符(三规则),如果您的类成员只是 POD 类型,则也不需要这些。

总结一下:即使对于不需要虚拟析构函数的类,您也会收到此警告,那么为什么要使用它呢?


2
投票

在该警告文档的链接中,它解释了 Microsoft 的推理。

If a warning is off by default, most users would not want to see it.


1
投票

我认为使用 Mixin 类模式的人可能会受到很多警告。

WikiPedia:在面向对象的编程语言中,mixin 是一个类,它提供某种功能供子类继承或重用,但不用于实例化(生成该类的对象)。 Mixin 是抽象基类的同义词。从 mixin 继承并不是一种专门化的形式,而是一种收集功能的方法。一个类或对象可以从一个或多个 mixins 中“继承”其大部分或全部功能,因此 mixins 可以被认为是一种多重继承机制。

示例:

混合班

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;
}

-3
投票

微软有时会对规范委员会未标记为“已弃用的功能”或某些“好的或坏的做法”发出警告。

如果该对象被设计为留在多态 OOP 环境中(其中

delete pObject
也必须正确地
delete pDerived
,即使使用
pObject
查看),那么在具有虚拟方法的对象中拥有非虚拟析构函数是一个潜在风险。 但这只是 C++ 支持的范例之一......因此这样的警告可能毫无意义:

此外,如果

p->dosomething()
不是虚拟的,则
Derived::dosomething
不会调用
dosomething
,但不会为此生成警告。

对我来说

delete p
,假装
P::~P()
导致调用
D::~D()
并不是特例,不应该受到警告。

但不幸的是,OOP 是 C++ 最初支持的第一个范式,也是大多数程序员、流通书籍和教师参考的范式,因此不幸的是,他们部署了最佳实践“如果析构函数不是虚拟的,则不要派生” Scot Meyers 在他的《Effective C++》中也对此进行了报道,从而使其变得“流行”,并且在没有技术原因使其继续存在的情况下也不断被提及。

今天是一个无意义的事情,就像大多数“不要这样做,不要那样做”(包括 Dijkstra 著名的“goto 被认为是有害的”,它对结构化编程做出了很多新的强调,但也有许多荒谬的方式旋转只是为了避免它。哈...Miscrosoft 还没有使用 goto 的警告...可能 Meyers 比 Djikstra 更有影响力??)

唯一的好习惯是“如果你不知道自己在做什么,就不要做任何事情!”。 没有什么禁止接受建议,但“最佳实践”并不是“总是好的实践”(否则它不会是“最佳”:只是“唯一”)并且编译器(作为正式工具)不应警告主观感受。

© www.soinside.com 2019 - 2024. All rights reserved.