我正在为UTF-8字符串编写一个字符串类,我遇到了设计问题。
我希望我的一些方法同时将const char *
和const Utf8String &
作为输入值。这是为了避免在用户通过Utf8String
时计算长度并验证UTF-8字符串,并避免在用户通过{{1}时为临时Utf8String
分配无用的内存}}
我还想重载const char *
运算符(相当于const char *
)因为它很方便。问题在于它会产生一种模糊性。
这就是STL字符串提供string::c_str()
方法而不是重载运算符c_str()
的原因吗?
我能在这做什么?保留重载的运算符const char *
,并且只有我的方法的两个可能签名之一(const char *
或const char *
),或删除const Utf8String &
运算符重载并保持两者可能方法签名?
答案 0 :(得分:1)
我建议编写两种方法,而不是使用(const char*)
运算符。它可能会导致各种问题。
问题是,如何管理返回指针的内存?
可以编写这样的致命代码:
const char* getText() {
YourType x = "text";
return x;
}
在这里,您的类型被破坏,并且很可能也是您的char数组。但这个编译很好,看起来也很好。很难发现代码中的问题。
使用专用方法可以让您明确使用:
class YourType {
public:
const char* createCharArray() const;
const char* accessCharArray() const;
}
一个方法将分配一个新的char数组,而另一个方法将只创建一个内部临时char表示,该表示将使用该类型本身销毁。
另一个问题是使用这样的构造函数:
class YourType {
public:
YourType(const char *str);
}
实际上并不清楚这个构造函数的作用。您的类是否存储指向字符串的指针,或者您的类是否创建了字符串的内部副本。这很可能导致代码难以理解。
void printText(const YourType &text) {
}
允许这样:
printText("Text");
但也适用于此:
void foo(const char* text) {
char *str = new char[strlen(text)+1];
std::strcpy(str, text);
printText(str);
}
我建议您使用static
转换方法:
class YourType {
public:
static YourType fromCharArray(const char *str);
}
答案 1 :(得分:0)
编写自己的字符串类非常有趣(并且是一个很好的练习)。但我发现标准std::string
非常适用于UTF-8字符串。
在我完全偏离主题之前,我对你的问题的回答是:当有疑问时,模仿标准事物(即std::string
)。至少有两个原因可以解决这个问题。 首先,这些接口通常设计得很好(因为许多具有不同背景的人正在研究它们)。 第二,开发人员通常已经知道如何正确使用这些东西。
但回到UTF-8字符串。我不知道为什么你需要一个单独的类来表示UTF-8字符串以及你花了多少时间思考你是否真的需要它(我很好奇你知道原因)。问题是UTF-8是Unicode标准的一部分,并不那么简单。如果你想要一个功能齐全的UTF-8字符串,你最终会实现unicode标准的一个不错的部分(比如规范化形式,奇怪的大写规则(你知道吗,希腊语字母Sigma有不同的大小写规则)在这个词的末尾?),等等。我确定你不想这样做,因为如果你需要它,最好使用ICU,Qt或其他一些具有良好Unicode支持的库。
所以,如果你需要的只是一个Utf-8字符的存储,其中有一些utf8_to_encoding()
,utf8_from_encoding()
,utf8_next_code_point()
我建议坚持std::string
并提供其他作为免费功能所需的功能。例如:
std::string utf8_from_utf16(const uint16_t *s, size_t len);
也许关于类似主题的我another answer也可能有用。