【问题标题】:Creating new exception in C++在 C++ 中创建新异常
【发布时间】:2010-10-09 07:14:45
【问题描述】:

我有一个 C++ 类,我正在尝试在 Ubuntu 中运行它:

#ifndef WRONGPARAMETEREXCEPTION_H_
#define WRONGPARAMETEREXCEPTION_H_

#include <iostream>
#include <exception>
#include <string>

using namespace std;

#pragma once

class WrongParameterException: public exception
{
    public:
        WrongParameterException(char* message): exception(message) {};
        virtual ~WrongParameterException() throw() {};
}; 

#endif

当我尝试编译它时,编译器给了我这个错误:

WrongParameterException.h: In constructor ‘WrongParameterException::WrongParameterException(char*)’:
WrongParameterException.h:14: error: no matching function for call to ‘std::exception::exception(char*&)’
/usr/include/c++/4.3/exception:59: note: candidates are: std::exception::exception()
/usr/include/c++/4.3/exception:57: note: std::exception::exception(const std::exception&)

谁能告诉我我做错了什么?我尝试将消息变量更改为 stringconst stringconst string&amp; 但没有帮助。

这是我如何使用从 main 创建的新异常:

try
{
     if ((strToInt1 == -1) || (parameters[1] == NULL) || (strToInt3 == -1) || (parameters[3] != NULL))
     {
          throw WrongParameterException("Error in the config or commands file");
     }
}
catch(WrongParameterException e)
{
     log.addMsg(e.what());
}

【问题讨论】:

  • 与问题无关,但很重要:不要在标题中use namespace std;。其次,了解 C++ 提供的标准异常类(std::runtime_error、logic_error 和 domain_error 等)。由 const& 捕获。并且不要将 包含在异常标头中。

标签: c++ linux exception ubuntu


【解决方案1】:

首先,#pragma once 是错误的做法,了解标头包含守卫。 Related question on SO 解释了为什么使用 #pragma once 是错误的方法。 Wikipedia 解释了如何使用 include guards,它具有相同的目的而没有任何缺点。

其次,您正在使用它不知道的参数调用 std::exception 的构造函数,在本例中是指向字符数组的指针。

#include <stdexcept>
#include <string>

class WrongParameterException : public std::runtime_error {
public:
    WrongParameterException(const std::string& message) 
        : std::runtime_error(message) { };
};

可能是你想要的。有关异常的更多信息,请查看 cplusplus.com 上的 C++ FAQ Lite article on Exceptionsexceptions article

祝你好运!

【讨论】:

  • 标头保护更加正确和可移植,但是如果您知道代码将使用 MS 编译器进行编译,那么 #pragma once 将使您的编译速度更快(它没有解析文件再次找到匹配的#endif)。
  • 他指定他在 Ubuntu 上运行它,所以我假设它是 GCC。在这种情况下,PRAGMA 语句首先不起作用。
  • 我很确定 #pragma once 受到撰写此评论时当前的 gcc 版本的支持。如果没有,它现在支持 - gcc.gnu.org/onlinedocs/gcc-4.6.2/cpp/…
  • #pragma oncepretty widely supported。此外,我的古老企业环境使用 GCC 3.4.2,并且根据我的测试支持 #pragma once
  • #pragma 曾经在 MSVC、gcc 和 clang 上工作,使用它!手动方式的重复宏可能会导致构建噩梦
【解决方案2】:

std::exception 没有接受任何类型字符串的构造函数,只有一个返回异常描述的虚拟 what() 方法。

您必须自己存储字符串并从那里返回。

【讨论】:

    【解决方案3】:

    我的建议是:

    1. std::runtime_error 继承。正如上面 X-Istence 所建议的那样。从概念上讲,这是一个运行时错误,而且std::runtime_error 构造函数接受std::string 作为描述发生情况的参数。
    2. 关于捕获异常。我会使用 catch(WrongParameterException const& e) (注意 const 引用)而不是 catch(WrongParameterException e),因为首先,在您的情况下,异常通常是恒定的,而且,使用引用,您可以捕获 WrongParameterException 的任何子类,以防您的代码随着一些更精细的异常处理而发展。

    【讨论】:

      【解决方案4】:

      std::exception 的构造函数不接受字符串参数。你试图给它一个,这就是导致编译错误的原因。

      您需要存储您的字符串,最好将其作为 std::string 而非原始指针处理,然后从 what() 方法返回。

      【讨论】:

        【解决方案5】:

        看MS VS2K5中异常类的声明,你想要的构造函数是:

        exception (const char *const&);
        

        所以尝试将您的构造函数更改为:

        WrongParameterException (const char *const message)
        

        看看是否有帮助。否则,将指针存储在您自己的类中并实现所有相关方法。

        【讨论】:

          【解决方案6】:

          一个简单的解决方案是设计不同的异常。这是一个简单的例子:

          class MyException : public Exception
          {
          public:
             MyException(CString strError) { m_strError = strError; }
          
             CString m_strError;
          };
          

          然后,您可以随意使用您的异常消息。这是因为 Exception 没有除 String 之外的构造器,所以你必须自己去构造它。

          【讨论】:

            猜你喜欢
            • 2017-06-04
            • 1970-01-01
            • 2023-03-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-05-14
            • 2011-11-18
            • 2020-04-16
            相关资源
            最近更新 更多