自定义异常 class,使用基数 class,带有多个参数
custom exception class, using a base class, with multiple arguments
所以我正在为我正在编写的程序设置自定义异常 classes。我正在创建一个包罗万象的基础 class,我将主要将其用作通用异常。这个基础 class 将被其他几个自定义异常继承。这是基础 class 和一个额外的例外 classes,将有 10 多个子 classes 从父 class.
继承
#include <exception>
#include <string>
#include <string.h>
class AgentException : public std::exception
{
protected:
char *msg;
public:
AgentException() : msg("AgentException"){};
AgentException(char *m) : msg(m){};
AgentException(char *m, std::string d)
{
strcat(m, d.c_str()); //aware this fails. its a segmentation fault
};
~AgentException() = default;
const char *what() const throw()
{
return (const char *)msg;
}
};
class ConnectionFailed : public AgentException
{
private:
std::string eType = "ConnectionFailed";
public:
ConnectionFailed() : AgentException("ConnectionFailed"){};
ConnectionFailed(std::string d) : AgentException("ConnectionFailed: ", d){};
~ConnectionFailed() = default;
};
我知道上面的代码 what() 当前不会 return 任何东西,因为没有分配成员变量。我忽略了它,因为我从 strcat() 调用中遇到了分段错误。
我已经为父 class 创建了多个构造函数,因为有时我想要传递默认值、单个值,甚至两个参数。对于子 class,它总是至少将 class ID 传递给父,在某些情况下,我可能需要将字符串变量与 class 一起传递ID。字符串变量 std::string 是必须的。这些是我要使用的指令。
最初我在 classes 中将所有消息变量设置为 std::string,但我最终 运行 遇到了与以下相关的问题what() 函数。我不知道如何将 std::string 转换为 return 作为 const char*。在做了一些研究之后,我发现在异常 class 中使用字符串是一个坏主意,因为它会捕获任何可能在
中发生的异常
所以我将所有内容都转换回 const char*,但现在我似乎无法从 what()。这些问题都源于我无法弄清楚不同类型的串联。
通过对 AgentException class 的更改,我可以得到一些可以正常工作的东西 class。
protected:
char msg[100];
public:
// AgentException() : msg("AgentException"){};
// AgentException(char *m) : msg(m){};
AgentException(const char *m, std::string d)
{
strcpy(msg, m);
strcat(msg, d.c_str());
};
我可以使此更改在整体上起作用,但感觉这不是正确的方法。有人可以向我提供一些关于他们将对此设置进行的更改的见解吗?
我目前正在通过抛出 AgentException 或 ConnectionFailed 异常并捕获 Base AgentException 来进行测试。我一直在轮换,看看有没有什么不同的反应。
try
{
throw ConnectionFailed("test");
}
catch (const AgentException &e)
{
std::cout << "----------------" << std::endl;
std::cerr << e.what() << '\n';
std::cout << "_________________" << std::endl;
}
char *strcat( char *dest, const char *src );
...
The behavior is undefined if the destination array is not large enough for the contents of both src and dest and the terminating null character.
因此,如果您使用刚好足以存储 原始 字符串的 char*
调用此构造函数,然后尝试向其追加更多内容,您会得到未定义的行为。不要在不知道大小的缓冲区上调用 strcat
。你的第二个解决方案,你 pre-allocate 100 个字符(假设这对你的 use-case 来说足够了)然后使用 that 缓冲区是正确的。一个完全通用的解决方案将调用 strlen
两次并分配一个足够大的缓冲区来容纳两个字符串,但如果这只是一个简单的示例,则可能是 out-of-scope。
正如 Silvio 在另一条评论中提到的,如果缓冲区不能包含结果字符串,则不能使用 strcat
。在这种情况下,您还会遇到将 const char *
传递给 strcat
的问题,这是不可以的(文字字符串是常量)。
我建议您将 msg
变量更改为 std::string
。然后它将能够增长以容纳连接的消息,并为您管理内存。
class AgentException : public std::exception
{
protected:
std::string msg;
public:
AgentException() : msg("AgentException") {};
AgentException(const char *m) : msg(m){};
AgentException(const char *m, const std::string& d)
{
msg = m + d;
};
~AgentException() = default;
const char *what() const throw()
{
return msg.c_str();
}
};
class ConnectionFailed : public AgentException
{
public:
ConnectionFailed() : AgentException("ConnectionFailed"){};
ConnectionFailed(const std::string& d) : AgentException("ConnectionFailed: ", d){};
~ConnectionFailed() = default;
};
所以我正在为我正在编写的程序设置自定义异常 classes。我正在创建一个包罗万象的基础 class,我将主要将其用作通用异常。这个基础 class 将被其他几个自定义异常继承。这是基础 class 和一个额外的例外 classes,将有 10 多个子 classes 从父 class.
继承#include <exception>
#include <string>
#include <string.h>
class AgentException : public std::exception
{
protected:
char *msg;
public:
AgentException() : msg("AgentException"){};
AgentException(char *m) : msg(m){};
AgentException(char *m, std::string d)
{
strcat(m, d.c_str()); //aware this fails. its a segmentation fault
};
~AgentException() = default;
const char *what() const throw()
{
return (const char *)msg;
}
};
class ConnectionFailed : public AgentException
{
private:
std::string eType = "ConnectionFailed";
public:
ConnectionFailed() : AgentException("ConnectionFailed"){};
ConnectionFailed(std::string d) : AgentException("ConnectionFailed: ", d){};
~ConnectionFailed() = default;
};
我知道上面的代码 what() 当前不会 return 任何东西,因为没有分配成员变量。我忽略了它,因为我从 strcat() 调用中遇到了分段错误。
我已经为父 class 创建了多个构造函数,因为有时我想要传递默认值、单个值,甚至两个参数。对于子 class,它总是至少将 class ID 传递给父,在某些情况下,我可能需要将字符串变量与 class 一起传递ID。字符串变量 std::string 是必须的。这些是我要使用的指令。
最初我在 classes 中将所有消息变量设置为 std::string,但我最终 运行 遇到了与以下相关的问题what() 函数。我不知道如何将 std::string 转换为 return 作为 const char*。在做了一些研究之后,我发现在异常 class 中使用字符串是一个坏主意,因为它会捕获任何可能在
中发生的异常所以我将所有内容都转换回 const char*,但现在我似乎无法从 what()。这些问题都源于我无法弄清楚不同类型的串联。
通过对 AgentException class 的更改,我可以得到一些可以正常工作的东西 class。
protected:
char msg[100];
public:
// AgentException() : msg("AgentException"){};
// AgentException(char *m) : msg(m){};
AgentException(const char *m, std::string d)
{
strcpy(msg, m);
strcat(msg, d.c_str());
};
我可以使此更改在整体上起作用,但感觉这不是正确的方法。有人可以向我提供一些关于他们将对此设置进行的更改的见解吗?
我目前正在通过抛出 AgentException 或 ConnectionFailed 异常并捕获 Base AgentException 来进行测试。我一直在轮换,看看有没有什么不同的反应。
try
{
throw ConnectionFailed("test");
}
catch (const AgentException &e)
{
std::cout << "----------------" << std::endl;
std::cerr << e.what() << '\n';
std::cout << "_________________" << std::endl;
}
char *strcat( char *dest, const char *src );
...
The behavior is undefined if the destination array is not large enough for the contents of both src and dest and the terminating null character.
因此,如果您使用刚好足以存储 原始 字符串的 char*
调用此构造函数,然后尝试向其追加更多内容,您会得到未定义的行为。不要在不知道大小的缓冲区上调用 strcat
。你的第二个解决方案,你 pre-allocate 100 个字符(假设这对你的 use-case 来说足够了)然后使用 that 缓冲区是正确的。一个完全通用的解决方案将调用 strlen
两次并分配一个足够大的缓冲区来容纳两个字符串,但如果这只是一个简单的示例,则可能是 out-of-scope。
正如 Silvio 在另一条评论中提到的,如果缓冲区不能包含结果字符串,则不能使用 strcat
。在这种情况下,您还会遇到将 const char *
传递给 strcat
的问题,这是不可以的(文字字符串是常量)。
我建议您将 msg
变量更改为 std::string
。然后它将能够增长以容纳连接的消息,并为您管理内存。
class AgentException : public std::exception
{
protected:
std::string msg;
public:
AgentException() : msg("AgentException") {};
AgentException(const char *m) : msg(m){};
AgentException(const char *m, const std::string& d)
{
msg = m + d;
};
~AgentException() = default;
const char *what() const throw()
{
return msg.c_str();
}
};
class ConnectionFailed : public AgentException
{
public:
ConnectionFailed() : AgentException("ConnectionFailed"){};
ConnectionFailed(const std::string& d) : AgentException("ConnectionFailed: ", d){};
~ConnectionFailed() = default;
};