3

我有一个类需要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's cpp 中)const char*后缀,我想附加到用户提供的前缀。

怎么做?


顺便提一句。我听说过string。如果我可以使用string,我不会在这里问,关于const char*

4

7 回答 7

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.

于 2013-03-08T12:51:15.350 回答
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*返回的 byc_str()将保持有效。由于intermediateis ,不能在其上调用任何变异函数,因此使用内部缓冲区const应该没有问题。cls

于 2013-03-08T13:02:28.253 回答
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

于 2013-03-08T12:56:32.083 回答
0

更好地std::string用于将您的字符串放在一起。如果需要,您仍然可以致电std::string::c_str()获取const char*。也作为论据std::string::appendconst char*或使用+-operator。

这里

于 2013-03-08T12:53:36.490 回答
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”部分。它在这里代表什么?你想达到什么目的?

希望有帮助。

于 2013-03-08T12:55:16.667 回答
0

我看到两个选项,具体取决于您对价值持久性等的需求。

一,存储keystd::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;
  }
};
于 2013-03-08T13:04:58.423 回答
0

乍一看,你的问题看起来像是一个理论测验,但后来我想起可能有一个没有 STL 的嵌入式平台。
无论如何,您需要坚持使用老式 C 风格的函数:strlen、strcpystrcat
由于您使用的是类,我假设您的编译器也支持运算符 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;
};

我没有调试这段代码,但它编译得很好,虽然它看起来相当混乱...... :)
不要忘记释放析构函数中的缓冲区。
祝你好运!

于 2013-03-08T13:33:52.040 回答