警告C4673:抛出'ex :: traced_error <EX>'将不会在catch网站上考虑以下类型

Joh*_*ing 5 c++ visual-studio-2010 visual-studio-2008

MSVC 10和MSVC 9在编译我的异常框架时都会生成4级警告消息,尽管程序的行为似乎是正确的.异常框架相当庞大和复杂,但我已经设法将其归结为其本质.这是一个可以在VS10中编译和运行的完整程序

#include <cstdlib>
#include <stdexcept>
#include <string>
#include <iostream>
#include <sstream>
using namespace std;

    namespace ex
    {
        class generic_error : virtual public std::exception
        {
        public:
            generic_error(int thread_id) : thread_id_(thread_id) {}
            const char* what() const throw()
            {
                static std::string msg;
                stringstream ss;
                ss << "generic error in thread #" << thread_id_;
                msg = ss.str();
                return msg.c_str();
            }
            int thread_id_;
        };

        template<class EX>
        class traced_error : virtual public std::exception, virtual public EX
        {
        public:
            traced_error(int line, const EX& ex):   EX(ex), line_(line) { }
            const char* what() const throw()
            {
                static std::string msg;
                stringstream ss;
                ss << "traced error on line " << line_ << " : '" << EX::what() << "'";
                msg = ss.str();
                return msg.c_str();
            }
            int line_;
        };

        template<class EX> traced_error<EX> make_traced_error(int line, const EX& ex)
        {
            return traced_error<EX>(line, ex);
        }
}

    int main()
    {
        try
        {
            throw ex::make_traced_error(__LINE__, ex::generic_error(234));
        }
        catch( const ex::generic_error& gex )
        {
            cout << "gex = " << gex.what();
            return 2;
        }
        catch( const exception& ex )
        {
            cout << ex.what();
            return 1;
        }
    }
Run Code Online (Sandbox Code Playgroud)

在编译该行时throw ex::make_traced_error(__LINE__, ex::generic_error(234)); ,编译器会发出:

1>hacks_vs10.cpp(51): warning C4673: throwing 'ex::traced_error<EX>' the following types will not be considered at the catch site
1>          with
1>          [
1>              EX=ex::generic_error
1>          ]
Run Code Online (Sandbox Code Playgroud)

此异常库的目标之一是将源文件信息附加到每个抛出的异常.我使用一个评估为的宏throw ex::make_traced_error(__FILE_, __LINE__, ex);,但没有必要复制编译器警告.

make_traced_error实例化一个模板异常类,在这种情况下,模板参数是抛出的异常generic_error.显然,如果我简单地抛出一个简单generic_error的编译器很高兴,但这不是我想要做的.

这个警告的原因和结果是什么?编译器错了,还是我的代码?我应该在这里注意几件事.

首先,当我执行此代码时,它会执行我期望它执行的操作.的generic_errorcatch程序块被称为而不是一般的exception块,并且该程序的输出结果是:

第51行的gex =跟踪错误:

其次,当我使用Comeau在线编译器编译此代码时,它编译时没有错误或警告,向我建议我的代码是符合标准且合法的C++.正确的假设?

线程#234中的一般错误

最后,我已经看过有关此警告的MS知识库文章.但MS的解释完全不令人满意(它没有解释警告的原因),而且他们的解决方案是不可接受的 - 他们说我应该直截了当generic_error.

Mic*_*ter 6

问题是间接地来自多个虚拟继承std::exception.编译器因此而感到困惑,但忘了告诉你原因.: - /

James McNellis是对的:编译器承诺会提到一种类型,但事实并非如此.尝试没有template:

#include <stdexcept>

class Base: virtual public std::exception {};
class Derv: public Base, virtual public std::exception {};

int main()
{
  try {
    throw Derv();
  } catch (const Base &) {
    return 2;
  } catch (...) {
    return 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

使用4级警告进行编译时,这仅仅表示:

警告C4673:投掷'Derv'将不会在捕获站点考虑以下类型

我看到了警告的价值.但在这种情况下,显然4级是错误的.由于所有工作都按预期工作,你可以让编译器沉默:

#pragma warning(disable: 4673)
Run Code Online (Sandbox Code Playgroud)

我想你可以将这个案例作为一个错误报告给微软.编译器应说明类型和问题所在.