了解 C4673 编译器警告

Posted

技术标签:

【中文标题】了解 C4673 编译器警告【英文标题】:Understanding C4673 compiler warning 【发布时间】:2015-07-22 11:50:42 【问题描述】:

关于警告C4673 的 MSDN 文章包含此示例,该示例发出带有特定消息的警告:

Base: this base class is inaccessible
// C4673.cpp
// compile with: /EHsc /W4
class Base 
private:
   char * m_chr;
public:
   Base() 
      m_chr = 0;
   

   ~Base() 
      if(m_chr)
         delete m_chr;
   
;

class Derv : private Base 
public:
   Derv() 
   ~Derv() 
;

int main() 
   try 
      Derv D1;
      // delete previous line, uncomment the next line to resolve
      // Base D1;
      throw D1;   // C4673
   

   catch(...) 

很遗憾,MSDN 文章没有对这​​个问题给出任何解释。我不明白上面的代码有什么问题。为什么会发出警告?

这是 MSVC 2013 - v120 工具集。

【问题讨论】:

看不到代码很难提供任何建议 @Petr:正如我所说,代码在 MSDN 文章中。我把它贴在这里。 那么我建议将您的问题改写为“我不明白...的示例”,并且根本不提及您的代码。 FWIW,我发现this SO Q&A 似乎表明此特定警告有时会在没有正当理由的情况下发出。同样 FWIW,我已向 MSDN 添加了反馈,即有关警告的文章没有帮助,因为它没有指出警告 关于 的内容。我假设这是特定于 MSVC 的异常处理机制的东西。 @Barry: catch 没关系,警告是在throw 站点生成的,似乎不受catch 的影响。 【参考方案1】:

我可以在webcompiler 上复制此内容,警告的全文是:

main.cpp(28): 警告 C4673: throwing 'Derv' 在捕获站点将不考虑以下类型 main.cpp(28): 警告 C4670: 'Base': 这个基类不可访问

确实如此。如果我们有:

try 
    throw Derv();

catch (Base& ) 
    std::cout << "I caught it!";

该处理程序与Derv 异常不匹配,因为Derv 私下继承自Base,因此无法访问基类。所以在这个例子中,异常不会被捕获。

但是,在 MSDN 示例中发出一个奇怪的警告,异常将被捕获:

catch(...) 

因此,该警告似乎实际上并没有检查任何内容 - 它只是一个一般性警告,表明您可能正在做一些有害的事情,而没有实际检查您是否存在。这对我来说似乎不是一个特别有用的警告。如果我们被Base&amp; 追赶,是的 - 告诉我这不会发生 - 但我们正在追赶...

【讨论】:

原来如此!私人继承!我没有注意到。将其更改为公开即可解决问题。 ...并在示例中添加catch( Base &amp; ),或者甚至省略catch( ... ),都会清楚地说明警告的含义。另一个 MS 宝石... 警告catch (Base&amp;) 是不正确的。假设有一个翻译单元包含 Base 的定义,但不包含 Derv。编译器不会知道 Derv 是从 Base 私有继承的,因此它无法发出警告。【参考方案2】:

这是一个更精简的例子:

class Base  public: virtual ~Base()  ;

class Derived : private Base ;

int main()

    Derived d;
    throw d;  // C4673

这里的问题是,开发人员可能会编写像这样的throw 语句作为任何函数的一部分,然后期望生成的异常被多态地捕获为Base。这不起作用,因为继承是private。您必须抓住Derived...

此处适合使用警告的原因是您不只是throw 任何对象。通常,您有专门用于此目的的特定异常类型。对此类异常类型使用私有继承没有任何意义。它只会引入像这样令人困惑的行为,但没有真正的用例。

不幸的是,我们可以检测一个类是否是异常类型的唯一地方是throw,所以这是我们可以生成此警告的唯一地方。

【讨论】:

以上是关于了解 C4673 编译器警告的主要内容,如果未能解决你的问题,请参考以下文章

C 语言学习的第 04 课:编译器常见错误和警告

警告:解析问题:使用GNU老式字段指示符扩展名

QuartusII编译与仿真之warning大解析

警告:表达式从“字符串?”隐式强制去任何

跟编译器警告说拜拜

添加我自己的编译器警告