我有一个类需要在构造期间连接两个const char*
字符串,甚至在初始化列表中使用结果(连接字符串)。
const char* SUFFIX = "suffix";
class widget {
public:
widget(const char* prefix) : key(???), cls(key) { };
private:
const char* key;
const important_class cls;
}
widget("prefix_"); // key should be prefix_suffix
我想要附加到用户提供的前缀的全局(widget
的cpp)const char*
后缀。
怎么做?
BTW。我听说过string
。如果我可以使用string
,我不会在此问及const char*
答案 0 :(得分:3)
使用std::string
会使您的问题成为一项微不足道的任务:
const std::string SUFFIX = "suffix";
class widget {
public:
widget(std::string const & prefix)
: key(prefix + SUFFIX), cls(key)
{ } // ^^^^^^^^^^^^^^concatenation!
private:
const std::string key;
const important_class cls;
}
widget("prefix_");
如果您需要const char*
,您仍然可以通过返回key.c_str()
的callng const char*
获取它。所以在你的情况下,它会给你 c-string "prefix_suffix"
。
另请注意,您已正确完成声明的顺序:cls
必须在 key
之后声明,因为其构造取决于key
答案 1 :(得分:2)
使用std::string
作为中间值:
const char* SUFFIX = "suffix";
class widget {
public:
widget(const char* prefix) :
intermediate(string(prefix) + suffix),
key(intermediate.c_str()),
cls(key) {
}
private:
const std::string intermediate;
const char* key;
const important_class cls;
}
widget("prefix_"); // key should be prefix_suffix
这里与您的代码唯一不同的是私有成员变量intermediate
。
std::string
对象intermediate
管理保持连接所需的动态内存。它会在异常,分配,复制等情况下很好地清理。
只要string
未发生变异,const char*
返回的c_str()
仍然有效。由于intermediate
是const
,因此不能在其上调用变异函数,因此使用内部缓冲区时cls
不应该出现问题。
答案 2 :(得分:1)
您应该使用std :: string(或项目使用的任何字符串类)。这将使这更容易,并避免问题,以使这个异常安全。
如果你坚持,
widget(const char* prefix) :
key(strcat(strcpy(new char[strlen(prefix)+strlen(SUFFIX)+1], prefix), SUFFIX)),
cls(key) { }
会以C方式做到。
important_class
的构造函数不应抛出异常。
如果您需要使用生成的key
初始化cls
,请务必保留声明顺序。
答案 3 :(得分:0)
最好使用std::string
将字符串组合在一起。如果需要,您仍然可以致电std::string::c_str()
获取const char*
。 std::string::append
也以const char*
为参数。或者使用+
- 运算符。
请参阅here。
答案 4 :(得分:0)
我不确定您是否可以在初始化列表中执行此操作。当然,其他一些有更多经验的用户可以帮助...当然,这听起来很明显但你可以使用std :: string然后去:
class widget
{
public:
widget(const char* prefix) : key(prefix)
{
string_key.append(suffix);
};
private:
const char* key;
std::string string_key;
};
当然,您可以这样做:
class widget
{
public:
widget(const char* prefix) : key(prefix)
{
key.append(suffix);
};
private:
std::string key;
};
我错过了整个“important_class”部分。它在这里代表什么?你想要实现什么目标?。
希望有所帮助。
答案 5 :(得分:0)
我看到两个选项,具体取决于您对价值持续性的需求等。
一,将key
存储为std::string
:
const char* SUFFIX = "suffix";
class widget{
public:
widget(const char* prefix) : key(std::string(prefix) + suffix), cls(key.c_str())
{}
private:
std::string key;
const important_class cls;
};
二,使用静态初始化函数,如下所示:
const char* SUFFIX = "suffix";
class widget{
public:
widget(const char* prefix) : key(concat_(prefix, suffix)), cls(key)
{}
private:
const char* key;
const important_class cls;
static const char* concat_(const char* a, const char* b)
{
std::string val(a);
val += b;
char* ret = new char[val.size() + 1];
strcpy(ret, val.c_str());
return val;
}
};
答案 6 :(得分:0)
乍一看,你的问题看起来像是一个理论测验,但后来我回忆起可能有一个没有STL的嵌入式平台。
无论如何,你需要坚持老式的C风格功能:strlen,strcpy和strcat。
由于您正在使用类,我认为编译器也支持operator new。
在我编写最终代码之前,您需要采取以下步骤来连接字符串:
const char* key;
key = new char[strlen(prefix) + strlen(SUFFIX) + 1];
strcpy(key, prefix);
strcat(key, SUFFIX);
...
delete [] key;
幸运的是strcpy和strcat都返回目的地 以下是您的代码的外观:
#include <string.h>
class widget {
public:
widget(const char* prefix)
: key(strcat(strcpy(new char[strlen(prefix) + strlen(SUFFIX) + 1], prefix), SUFFIX))
, cls(key) { };
private:
const char* key;
const important_class cls;
};
我没有调试这段代码,但编译得很好,虽然它看起来很混乱...... :) 不要忘记在析构函数中释放缓冲区 祝你好运!