了解 C4673 编译器警告
Understanding C4673 compiler warning
有关警告的 MSDN 文章 C4673 包含此示例,该示例发出带有特定消息的警告:
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 工具集。
我可以在 webcompiler 上重现这个警告的全文是:
main.cpp(28): warning C4673: throwing 'Derv
' the following types will not be considered at the catch site
main.cpp(28): warning C4670: 'Base
': this base class is inaccessible
没错。如果我们有:
try {
throw Derv();
}
catch (Base& ) {
std::cout << "I caught it!";
}
该处理程序不匹配 Derv
异常,因为 Derv
从 Base
私有继承,因此基 class 不可访问。所以在这个例子中,异常是未被捕获的。
但是,像 MSDN 示例中那样发出一个奇怪的警告,异常将被捕获:
catch(...) {}
所以看起来警告实际上并没有检查任何东西 - 它只是一个一般性的警告,你可能正在做一些有害的事情,而没有实际检查你是否这样做。这对我来说似乎不是特别有用的警告。如果我们在 Base&
之前赶上,是的 - 告诉我这不会发生 - 但我们在 ...
之前赶上。
这是一个更简化的例子:
class Base { public: virtual ~Base() {} };
class Derived : private Base {};
int main()
{
Derived d;
throw d; // C4673
}
这里的问题是,开发人员可能会像这样编写一个 throw
语句作为任何函数的一部分,然后期望由此产生的异常被多态地捕获为 Base
。这行不通,因为继承是 private
。您必须赶上 Derived
或 ...
.
之所以在这里发出警告是合适的,是因为您不只是 throw
任何对象。通常,您有专门用于此目的的特定异常类型。对此类异常类型使用私有继承没有任何意义。它只会引入像这样令人困惑的行为,但没有真正的用例。
不幸的是,我们唯一可以检测到 class 是否为异常类型的地方是 throw
,因此这是我们唯一可以生成此警告的地方。
有关警告的 MSDN 文章 C4673 包含此示例,该示例发出带有特定消息的警告:
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 工具集。
我可以在 webcompiler 上重现这个警告的全文是:
main.cpp(28): warning C4673: throwing '
Derv
' the following types will not be considered at the catch site
main.cpp(28): warning C4670: 'Base
': this base class is inaccessible
没错。如果我们有:
try {
throw Derv();
}
catch (Base& ) {
std::cout << "I caught it!";
}
该处理程序不匹配 Derv
异常,因为 Derv
从 Base
私有继承,因此基 class 不可访问。所以在这个例子中,异常是未被捕获的。
但是,像 MSDN 示例中那样发出一个奇怪的警告,异常将被捕获:
catch(...) {}
所以看起来警告实际上并没有检查任何东西 - 它只是一个一般性的警告,你可能正在做一些有害的事情,而没有实际检查你是否这样做。这对我来说似乎不是特别有用的警告。如果我们在 Base&
之前赶上,是的 - 告诉我这不会发生 - 但我们在 ...
之前赶上。
这是一个更简化的例子:
class Base { public: virtual ~Base() {} };
class Derived : private Base {};
int main()
{
Derived d;
throw d; // C4673
}
这里的问题是,开发人员可能会像这样编写一个 throw
语句作为任何函数的一部分,然后期望由此产生的异常被多态地捕获为 Base
。这行不通,因为继承是 private
。您必须赶上 Derived
或 ...
.
之所以在这里发出警告是合适的,是因为您不只是 throw
任何对象。通常,您有专门用于此目的的特定异常类型。对此类异常类型使用私有继承没有任何意义。它只会引入像这样令人困惑的行为,但没有真正的用例。
不幸的是,我们唯一可以检测到 class 是否为异常类型的地方是 throw
,因此这是我们唯一可以生成此警告的地方。