关于警告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工具集。
答案 0 :(得分:6)
我可以在webcompiler上重现这一点,警告的全文是:
main.cpp(28):警告C4673:投掷'
Derv
'在捕捞地点不会考虑以下类型 main.cpp(28):警告C4670:'Base
':此基类无法访问
这是事实。如果我们有:
try {
throw Derv();
}
catch (Base& ) {
std::cout << "I caught it!";
}
该处理程序与Derv
异常不匹配,因为Derv
从Base
私下继承,因此基类不可访问。所以在这个例子中,异常将是未被捕获的。
但是,如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
,因此这是我们可以生成此警告的唯一地方。