为什么C4265是Visual C++;默认情况下关闭警告(虚拟成员函数和无虚拟析构函数)? VisualC++可以在类至少有一个虚成员函数而没有虚析构函数时发出。

为什么C4265是Visual C++;默认情况下关闭警告(虚拟成员函数和无虚拟析构函数)? VisualC++可以在类至少有一个虚成员函数而没有虚析构函数时发出。,c++,visual-c++,compiler-construction,destructor,compiler-warnings,C++,Visual C++,Compiler Construction,Destructor,Compiler Warnings,显然,当派生类对象通过指向基类的指针deleted,并且基类中没有虚拟析构函数时,会出现警告来检测这种情况。这种情况会产生未定义的行为。顺便说一下,我在Visual C++中通过启用C4265,在一个相当大的代码库中找到了这种情况的例子。 默认情况下,此警告处于关闭状态 为什么??如果我启用它并在发出警告的每个类中添加虚拟析构函数,会发生什么情况?在中,对于该警告的文档,它解释了Microsoft的推理如果警告在默认情况下处于关闭状态,大多数用户都不希望看到它。我的猜测是,有时您不需要虚拟析构函

显然,当派生类对象通过指向基类的指针
delete
d,并且基类中没有虚拟析构函数时,会出现警告来检测这种情况。这种情况会产生未定义的行为。顺便说一下,我在Visual C++中通过启用C4265,在一个相当大的代码库中找到了这种情况的例子。 默认情况下,此警告处于关闭状态


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

在中,对于该警告的文档,它解释了Microsoft的推理
如果警告在默认情况下处于关闭状态,大多数用户都不希望看到它。

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

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

虚拟析构函数还意味着您应该实现一个复制构造函数和一个赋值操作符(三个规则),如果您的类成员只是POD类型,则也不需要它们


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

Microsoft有时会对未经规范委员会标记的“弃用函数”或某些“好的或坏的做法”发出警告

如果在具有虚拟方法的对象中具有非虚拟析构函数,则该对象被设计为留在多态OOP环境中(其中
delete pObject
也必须正确
delete pDerived
,即使使用
pObject
查看),则该对象具有潜在风险。 但这只是C++的范例支持之一…因此,此类警告可能毫无意义:

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

对我来说,
delete p
,假装
p::~p()
导致调用
D::~D()
不是特例,不应该受到警告

但是-不幸的是,OOP是最初支持C++的最初范例,也是程序员和流通书籍和教师所引用的范例,因此他们部署了最佳的实践“如果析构函数不是虚拟的,就不要推导”,不幸的是,Scot Meyers在他的“有效C++”中也报告了它,从而使它成为“流行的”。如果没有继续存在的技术原因,也可以继续引用

今天是一个非理性的世界,就像大多数的“不要做这个,不要做那个”(包括著名的“goto被认为是有害的”Dijkstra,这使得许多新的重点放在结构化编程上,但也有许多可笑的方法来绕开它。哈…Mistrosoft还没有关于使用goto的警告…也许Meyers比Djikstra更有影响力??)

唯一的好做法是“如果你不知道自己在做什么,就什么都不要做!”。
没有任何东西禁止接受建议,但“最佳实践”并不是“始终良好的实践”(否则它将不是“最佳的”:将只是“唯一的”),编译器(作为正式工具)不应该对主观感受发出警告。

我想,在使用模式混合类的人中,可能会有很多警告

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

例如:

混合班

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);
  }
};
模板结构AddNoEq{
虚拟布尔运算符==(常数T&cmp)常数=0;
布尔运算符!=(常数T和cmp)常数{
return!static_cast(this)->operator==(cmp);
}
};
使用:

struct Complex:public AddNoEq{
复数(int-re,int-im):re(re),im(im){
虚拟布尔运算符==(常量复数和cmp)常量{
返回cmp.re\u==this->re\u=&cmp.im\u==this->im;
}
// ...
私人:
int re_u,im_u;
};
int main()
{
配合物a(1,2),b(2,3);
如果(a!=b)

std::难道我不认为三的规则是这样的吗?一个空的虚拟析构函数对于多态删除来说就足够了。就是你已经得到的同一个析构函数(由编译器提供),只是
virtual
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;
}