std::string class 用 cstring API 包装(属性 代理模式)
std::string class wrapped with cstring API (property proxy pattern)
我想使用 std::strings 将遗留代码库中使用 cstrings 的静态数据结构转换为动态数据结构。问题是,现在,在我们的代码库中调整所有使用它们的函数是不可行的。
我建议使用包装器 class(属性 代理模式),它在内部使用 std::string 公开 cstring API。这将允许使用 cstring 函数(strcpy、strlen、memset 等)并使数据结构向后兼容。这是我目前所拥有的:
原始数据结构:
struct data
{
char property1[20];
char property2[20];
}
新结构:
struct data
{
CStringProperty property1;
CStringProperty property2;
}
包装器class:
class CStringProperty
{
public:
CStringProperty(){}
CStringProperty(std::string& value) : _value{value}{}
CStringProperty(char* value) : _value{value}{}
CStringProperty& operator=(std::string value)
{
_value = value;
return *this;
}
CStringProperty& operator=(char* value)
{
std::string valueStr = value;
return operator=(valueStr);
}
operator std::string()
{
return _value;
}
operator char*()
{
return &_value[0];
}
char& operator[](int i)
{
return _value[i];
}
std::string to_str()
{
return _value;
}
private:
std::string _value;
friend std::ostream& operator<<(std::ostream& os, CStringProperty& value);
};
std::ostream& operator<<(std::ostream& os, CStringProperty& value)
{
return os << value.to_str();
}
测试
int main()
{
CStringProperty a= "Hello";
std::cout << "Test 1: " << a << std::endl; // Works
CStringProperty b;
b = a;
std::cout << "Test 2: " << b << std::endl; // Works
CStringProperty c;
char d[10] = "Hello";
c = d;
std::cout << "Test 3: " << c << std::endl; // Works
char* e = a;
std::cout << "Test 4: " << e << std::endl; // Works
CStringProperty f;
std::cout << "Test 5: " << f << std::endl; // Works
CStringProperty g = "Hello";
g[0] = 'X';
std::cout << "Test 6: " << g << std::endl; // Works
CStringProperty h = "Hello";
std::cout << "Test 7: " << std::to_string(strlen(h)) << std::endl; // Works
CStringProperty p = "hello";
strcpy(p,"bye");
std::cout << "Test 8.1: " << std::to_string(strlen(p)) << std::endl; // Works
std::cout << "Test 8.2: " << p << std::endl; // Doesn't work
CStringProperty q;
strcpy(q,"bye");
std::cout << "Test 9.1: " << std::to_string(strlen(q)) << std::endl; // Works
std::cout << "Test 9.2: " << q << std::endl; // Doesn't work
return 0;
}
我知道 std::string::data() 暴露了底层的 cstring,但是这个 returns 是 const char*
,所以它显然只是为了阅读目的。使用 const_cast
我想会类似于我在上面所做的并导致未定义的行为。
如果知道没有办法做到这一点,我会非常气馁,因为这意味着真正巨大的重构工作,所以我感谢任何帮助或想法。
9.2 和 8.2 不起作用的原因是因为 std::string
有一个 size_
数据成员。 strcpy
函数不修改它。
您可以使用 friend
函数(或常规函数)解决此问题。
class CStringProperty
{
public:
CStringProperty(){}
CStringProperty(std::string const& value) : _value{value}{}
CStringProperty(char const* value) : _value{value}{}
CStringProperty& operator=(std::string value)
{
_value = value;
return *this;
}
CStringProperty& operator=(char* value)
{
std::string valueStr = value;
return operator=(valueStr);
}
operator std::string()
{
return _value;
}
operator char const*()
{
return _value.c_str();
}
char& operator[](int i)
{
return _value[i];
}
private:
std::string _value;
friend std::ostream& operator<<(std::ostream& os, CStringProperty const& value)
{
return os << value._value;
}
friend void strcpy(CStringProperty& value, char const* src)
{
value._value = src;
}
friend size_t strlen(CStringProperty const& value)
{
return value._value.size();
}
};
另一个问题是您没有在需要的地方使用 const
。而且您还按值传递 std::string
,这可能会影响性能。
我想使用 std::strings 将遗留代码库中使用 cstrings 的静态数据结构转换为动态数据结构。问题是,现在,在我们的代码库中调整所有使用它们的函数是不可行的。
我建议使用包装器 class(属性 代理模式),它在内部使用 std::string 公开 cstring API。这将允许使用 cstring 函数(strcpy、strlen、memset 等)并使数据结构向后兼容。这是我目前所拥有的:
原始数据结构:
struct data
{
char property1[20];
char property2[20];
}
新结构:
struct data
{
CStringProperty property1;
CStringProperty property2;
}
包装器class:
class CStringProperty
{
public:
CStringProperty(){}
CStringProperty(std::string& value) : _value{value}{}
CStringProperty(char* value) : _value{value}{}
CStringProperty& operator=(std::string value)
{
_value = value;
return *this;
}
CStringProperty& operator=(char* value)
{
std::string valueStr = value;
return operator=(valueStr);
}
operator std::string()
{
return _value;
}
operator char*()
{
return &_value[0];
}
char& operator[](int i)
{
return _value[i];
}
std::string to_str()
{
return _value;
}
private:
std::string _value;
friend std::ostream& operator<<(std::ostream& os, CStringProperty& value);
};
std::ostream& operator<<(std::ostream& os, CStringProperty& value)
{
return os << value.to_str();
}
测试
int main()
{
CStringProperty a= "Hello";
std::cout << "Test 1: " << a << std::endl; // Works
CStringProperty b;
b = a;
std::cout << "Test 2: " << b << std::endl; // Works
CStringProperty c;
char d[10] = "Hello";
c = d;
std::cout << "Test 3: " << c << std::endl; // Works
char* e = a;
std::cout << "Test 4: " << e << std::endl; // Works
CStringProperty f;
std::cout << "Test 5: " << f << std::endl; // Works
CStringProperty g = "Hello";
g[0] = 'X';
std::cout << "Test 6: " << g << std::endl; // Works
CStringProperty h = "Hello";
std::cout << "Test 7: " << std::to_string(strlen(h)) << std::endl; // Works
CStringProperty p = "hello";
strcpy(p,"bye");
std::cout << "Test 8.1: " << std::to_string(strlen(p)) << std::endl; // Works
std::cout << "Test 8.2: " << p << std::endl; // Doesn't work
CStringProperty q;
strcpy(q,"bye");
std::cout << "Test 9.1: " << std::to_string(strlen(q)) << std::endl; // Works
std::cout << "Test 9.2: " << q << std::endl; // Doesn't work
return 0;
}
我知道 std::string::data() 暴露了底层的 cstring,但是这个 returns 是 const char*
,所以它显然只是为了阅读目的。使用 const_cast
我想会类似于我在上面所做的并导致未定义的行为。
如果知道没有办法做到这一点,我会非常气馁,因为这意味着真正巨大的重构工作,所以我感谢任何帮助或想法。
9.2 和 8.2 不起作用的原因是因为 std::string
有一个 size_
数据成员。 strcpy
函数不修改它。
您可以使用 friend
函数(或常规函数)解决此问题。
class CStringProperty
{
public:
CStringProperty(){}
CStringProperty(std::string const& value) : _value{value}{}
CStringProperty(char const* value) : _value{value}{}
CStringProperty& operator=(std::string value)
{
_value = value;
return *this;
}
CStringProperty& operator=(char* value)
{
std::string valueStr = value;
return operator=(valueStr);
}
operator std::string()
{
return _value;
}
operator char const*()
{
return _value.c_str();
}
char& operator[](int i)
{
return _value[i];
}
private:
std::string _value;
friend std::ostream& operator<<(std::ostream& os, CStringProperty const& value)
{
return os << value._value;
}
friend void strcpy(CStringProperty& value, char const* src)
{
value._value = src;
}
friend size_t strlen(CStringProperty const& value)
{
return value._value.size();
}
};
另一个问题是您没有在需要的地方使用 const
。而且您还按值传递 std::string
,这可能会影响性能。