了解C4673编译器警告

时间:2015-07-22 11:50:43

标签: c++ visual-c++ visual-studio-2013

关于警告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工具集。

2 个答案:

答案 0 :(得分:6)

我可以在webcompiler上重现这一点,警告的全文是:

  

main.cpp(28):警告C4673:投掷' Derv'在捕捞地点不会考虑以下类型   main.cpp(28):警告C4670:' Base':此基类无法访问

这是事实。如果我们有:

try {
    throw Derv();
}
catch (Base& ) {
    std::cout << "I caught it!";
}

该处理程序与Derv异常不匹配,因为DervBase私下继承,因此基类不可访问。所以在这个例子中,异常将是未被捕获的。

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

catch(...) {}

所以警告似乎并没有真正检查任何事情 - 它只是一般性发布警告,你可能正在做一些有害的事情,而不会实际检查你是否有。对我来说,这似乎不是一个特别有用的警告。如果我们追赶Base&,是的 - 请告诉我这不会发生 - 但我们正在追赶...

答案 1 :(得分:3)

这是一个更简化的例子:

class Base { public: virtual ~Base() {} };

class Derived : private Base {};

int main()
{
    Derived d;
    throw d;  // C4673
}

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

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

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