我有这个代码示例,我尝试连接字符串:
const char* NameErrorException::what() const throw()
{
return "NameError : name '" + _name + "' is not defined";
}
为什么我不能在字符串之间使用char*
来创建+
?
答案 0 :(得分:6)
"芝麻街3"加上前面的4个房子意味着" Sesame Street 7"。
但" Sesame Street 3"再加上" Sesame Street 4"是什么意思?
它意味着什么。
你可以在街道地址上添加房屋抵消,但是将两个街道地址加在一起甚至意味着什么呢?这没有道理。 "芝麻街3"再加上" Sesame Street 4"不是" Sesame Street 7"。
const char*
是RAM上字符的位置。添加另一个位置不会创建新的字符串。这毫无意义。就像添加两个街道地址一样,不会创建一个新的街道地址(或者说是新街道)。
const char*
(通常)是C-String。它对字符串连接,拆分,删除或替换一无所知。它只是RAM上第一个字符的位置。这就是为什么通常在C ++中我们使用std::string
。 std::string
是一个有行为的对象。它知道连接,拆分,删除或替换等操作。
答案 1 :(得分:2)
char *
是指向char的指针。 +
运算符可用于向指针添加偏移量,而不是连接c字符串。
答案 2 :(得分:2)
第一部分很简单:你不能用+添加char *
变量,因为C ++不是Java(或Python,或C#)。
您可能已经了解到“const char*
表示C ++中的字符串”。这是事实,但如果您使用const char*
,那么您有责任在适当的时间分配和释放内存。
一般情况下,使用std::string
表示字符串会更好 。从函数返回std::string
是安全的 - 返回const char*
(谁负责释放内存)是不安全的?
但是,该规则有一个例外:当您覆盖std::exception::what()
时 - 定义为返回const char*
。解决方法是您需要一个std::string
成员NameErrorException
,您在构造_name
的同时构建它,并将其设置为完整的错误消息,然后what
只返回_what_error.c_str()
。所以全班看起来像是:
class NameErrorException : public std::runtime_error
{
std::string _name;
std::string _what_error;
std::string build_error(const std::string &name)
{
// Use std::string literals.
return "NameError : name '"s + name + "' is not defined"s;
}
public:
NameErrorException(const std::string& name)
: _name(name)
, _what_error(build_error(name))
{}
const char* what() const throw() override
{
return _what_error.c_str();
}
}
如果您没有std::string
文字,则必须使build_error
成为:
return std::string("NameError : name '") + name + "' is not defined"s;
答案 3 :(得分:-1)
您收到错误,因为operator+
未用于连接c字符串。 operator+
仅用于向指针添加索引值。
您可以通过在std::string
对象中创建NameErrorException
对象并在创建异常时(即在构造函数中)初始化它来解决此问题:
class NameErrorException : public std::runtime_error {
private:
std::string _errorString; // Used to store the error message.
public:
// Constructor.
NameErrorException(const char * const name) {
_errorString.append("NameError : name '");
_errorString.append(name);
_errorString.append("' is not defined");
}
virtual const char * what() {
return _errorString.c_str();
}
};
或者,您可以创建大小正确的第二个const char *
缓冲区,并使用std::snprintf()
或std::strncat()
创建字符串。 (记得清理析构函数中的新缓冲区!)