类std :: wstring缺少“普通”c字符串(和文字)的一些操作。
我想在我自己的自定义类中添加这些缺少的操作:
#include <string>
class CustomWString : public std::wstring {
public:
CustomWString(const char*);
const char* c_str(void);
};
上面的代码使用g ++ v4.4.1在Ubuntu Karmic上编译得很好。
但我想知道是否有反对这样做的论据?
编辑:一些例子来澄清“缺少操作”的含义:
std::wstring foo("hello"); // requires the L() macro or something like that
std::string bar("hello");
std::wstring goose(bar.c_str());
foo="hello"; // requires the L() macro
foo=bar.c_str();
foo=bar;
编辑:我想以某种方式“集中”。那是因为我有一个项目要从M $ -Windows移植,其中有数千个这些失败的操作。
好处是:有一个中心位置可以定义要使用的字符串类型,例如:
#ifdef WINDOWS_OS
typedef std::wstring AppStringClass;
#else
typedef std::string AppStringClass;
#endif
答案 0 :(得分:15)
这是合法的,但很多人认为这是不可取的。问题是标准库模板类没有虚拟析构函数。所以如果你编写这样的代码:
std::wstring * p = new CustomWString ;
...
delete p;
你有未定义的行为。
答案 1 :(得分:10)
编译器绝对允许你,因为没有办法用C ++中的公共构造函数来密封类。
STL容器不是为继承而设计的,所以这通常是一个坏主意。 C ++必须忽略许多奇怪的角落。您的派生类可能会破坏另一个STL实现,或者只是更新构建环境。
但是,我认为这是一个严厉的警示标志,而不是完全禁止。这是“你真的很确定你在做什么,你知道所有的影响,并且对所有选择有充分的理由”吗?
在您的情况下:提供额外的构造函数很好(因为公共接口已记录在案,您可以复制它),并且只要您不引入新数据成员或VMT,切片或非虚析构函数不是问题。 (请记住,在通过没有虚拟DTor的基类指针进行删除时,C ++标准声明了未定义的行为)
然而我不确定如何在不提供字符串存储的情况下实现char const * c_str()
。一旦你引入了新的数据成员,你就进入了一个地雷领域。
答案 2 :(得分:3)
我想你知道basic_string
没有定义虚拟析构函数。以多态方式使用wstring
是错误的。否则,您可以照常使用自定义类。
所以,以下是危险的:
vector<wstring*> mystrings;
mystrings.push_back(new CustomWString);
...
delete mystrings[0]; // No virtual destructor
直接使用您的自定义类就可以了,例如
vector<CustomWString> mystrings; // OK
mystrings.push_back("...");
答案 3 :(得分:3)
反对继承STL对象的传统观点是它们没有虚拟析构函数。所以,以矢量为例。如果我要继承它:
class CMyVect : public std::vector<int>
{
...
int* someMemory;
public:
CMyVect()
{
someMemory = new int();
}
~CMyVect()
{
delete someMemory;
}
};
基类中的非虚拟析构函数意味着如果用户指向CMyVect的ponter-to-vector-ints然后删除该指针,则不会调用析构函数,从而泄漏内存。也就是说:
int main()
{
std::vector<int>* vecPtr = new CMyVect();
delete vecPtr; // invokes vector constructor only, not yours
}
所以这并不是说你不能继承这些对象,但它可以解决这个问题。你必须小心如何使用你继承的对象,或者你不需要你的析构函数来解雇(不要保留任何需要释放的资源)。
答案 4 :(得分:3)
这是可能的,合法的。但这是一个坏主意。这些类不是为继承而设计的,扩展它们最好不需要继承。如果您在使用类时不小心,您将获得未定义的行为。 (这些类没有虚拟析构函数)
此外,添加这些特定功能似乎是一个坏主意,因为它们依赖于语言环境和编码。你给了全班不止一个人的责任。在char
和wchar_t
之间进行转换的功能属于其他地方。
答案 5 :(得分:2)
类模板std::basic_string
(其中std::wstring
是具有特定模板参数的typedef)不具有虚拟析构函数,因此,公开继承它是一个坏主意。
答案 6 :(得分:1)
你可以做到。但我认为没有意义,因为std :: basic_string (及其具体版本std :: string和std :: wstring) 定义没有虚拟方法并具有非虚拟析构函数。 所以没有办法,你可以正确使用你的子类代替例如的std :: wstring的。
答案 7 :(得分:0)
从一个类“继承”一个类的能力是一种语言特征。它只是一种正式,简单和干燥的语言功能,不依赖于任何特定的应用程序或任何特定的使用模型。它是一种低级工具,可用于不同目的。而且,为了回答你的问题,继承std::wstring
类是完全合法的。
但是,接下来的问题是“为什么”这个问题。为什么要继承std::wstring
?
如果您在OOP范例中设计代码,那么从std::wstring
继承公开可能不是一个好主意,“可能”在这里成为一个关键词。 OOP中的公共继承通常意味着多态类层次结构中的IS-A关系。类std::wstring
并不是多态的,这就是为什么公开继承它可能会被视为一件非常奇怪的事情。
如果您在不同的范例中设计代码,例如模板元编程(TMP),那么公共继承可能是完全有效的事情。你看,在TMP中,公共继承服务于一个完全不同的目的,甚至与多态性和关系无关。
换句话说,如果不考虑大局,就无法对问题做出具体的回答。在任何情况下,要注意“机械”答案,例如“因为std::wstring
没有虚拟析构函数,你不能继承它,因为它会破坏&lt;继续说明代码&gt; ”。即使在OOP方法中,这种推理也完全是假的。