C++ 是否允许从std命名空间(即std::wstring)中的类继承?
类std::wstring缺少“普通”c字符串(和文本)的一些操作 我想在我自己的自定义类中添加这些缺少的操作:C++ 是否允许从std命名空间(即std::wstring)中的类继承?,c++,gcc,stl,g++,C++,Gcc,Stl,G++,类std::wstring缺少“普通”c字符串(和文本)的一些操作 我想在我自己的自定义类中添加这些缺少的操作: #include <string> class CustomWString : public std::wstring { public: CustomWString(const char*); const char* c_str(void); }; 编辑:我希望以某种方式“集中化”。这是因为我有一个
#include <string>
class CustomWString : public std::wstring {
public:
CustomWString(const char*);
const char* c_str(void);
};
编辑:我希望以某种方式“集中化”。这是因为我有一个项目要从M$-Windows移植,其中有上千个失败的操作
好处是:有一个中心位置定义了要使用的字符串类型,例如:
#ifdef WINDOWS_OS
typedef std::wstring AppStringClass;
#else
typedef std::string AppStringClass;
#endif
类模板
std::basic_string
(其中std::wstring
是一个带有特定模板参数的typedef)没有虚拟析构函数,因此,公开继承它是一个坏主意。它是合法的,但许多人认为它不可取。问题是标准库模板类没有虚拟析构函数。因此,如果您曾经编写过这样的代码:
std::wstring * p = new CustomWString ;
...
delete p;
您有未定义的行为。您可以这样做。但我看不出有什么意义,因为std::basic_字符串 (及其具体版本std::string和std::wstring) 不定义虚方法,并具有非虚析构函数。
因此,您无法正确地使用子类来代替std::wstring。我想您知道
basic\u string
没有定义虚拟析构函数。以多态方式使用wstring
是错误的。否则,您可以像往常一样使用自定义类
因此,以下情况是危险的:
vector<wstring*> mystrings;
mystrings.push_back(new CustomWString);
...
delete mystrings[0]; // No virtual destructor
向量mystrings;
mystrings.push_back(新自定义字符串);
...
删除mystring[0];//没有虚拟析构函数
直接使用自定义类是可以的,例如
vector<CustomWString> mystrings; // OK
mystrings.push_back("...");
vector mystrings;//好啊
mystrings.push_back(“…”);
反对从STL对象继承的传统论点是,它们没有虚拟析构函数。以向量为例。如果我从中继承:
class CMyVect : public std::vector<int>
{
...
int* someMemory;
public:
CMyVect()
{
someMemory = new int();
}
~CMyVect()
{
delete someMemory;
}
};
类CMyVect:public std::vector
{
...
int*someMemory;
公众:
CMyVect()
{
someMemory=newint();
}
~CMyVect()
{
删除一些记忆;
}
};
基类中的非虚拟析构函数意味着,如果该类的用户将一个ponter to ints向量指向一个CMyVect,然后删除该指针,则不会调用析构函数,从而导致内存泄漏。也就是说:
int main()
{
std::vector<int>* vecPtr = new CMyVect();
delete vecPtr; // invokes vector constructor only, not yours
}
intmain()
{
std::vector*vecPtr=new CMyVect();
delete vecPtr;//仅调用向量构造函数,而不是您的
}
这并不是说你不能从这些对象继承,但是这个问题可以解决。你必须小心使用你继承的对象,或者C++不需要你的析构函数来启动(不保存任何需要释放的资源)。
STL容器不是为继承而设计的,所以这通常不是一个好主意。C++有许多奇怪的角来忽略它。派生类可能会因另一个STL实现而中断,或者仅因生成环境的更新而中断
但是,我认为这是一个警戒信号,而不是完全的警告。这是一个“你真的确定你在做什么,你知道所有的含义,并且对所有的选择都有很好的理由吗?”
在您的情况下:提供额外的构造函数是可以的(因为公共接口是文档化的,您可以复制它),只要您不引入新的数据成员或VMT,切片或非虚拟析构函数就不是问题。(记住,C++标准在删除没有虚拟DTor的基类指针时声明未定义行为)
但是我不确定在不为字符串提供存储的情况下如何实现char const*c_str()
。一旦你引入新的数据成员,你就进入了一个地雷的领域 这是可能的,也是合法的。但这是个坏主意。这些类不是为继承而设计的,扩展它们最好不要继承。如果在使用这些类时不小心,就会出现未定义的行为。(类没有虚拟析构函数)
此外,添加这些特定函数似乎不是一个好主意,因为它们依赖于区域设置和编码。你给了全班不止一个责任。在char
和wchar\u t
之间转换的功能属于其他地方。从一个类“继承”另一个类的能力是一种语言特性。它只是一个正式、简单、枯燥的语言特性,与任何特定的应用程序或任何特定的使用模型无关。它是一个低级工具,可以用于不同的目的。为了回答您的问题,从std::wstring
类继承是完全合法的
然而,下一个问题是“为什么”的问题。为什么要从std::wstring
继承
如果您是在OOP范式中设计代码,那么从std::wstring
公开继承可能不是一个好主意,“may”在这里是一个关键词。OOP中的公共继承通常意味着多态类层次结构中的IS-A关系。类std::wstring
不是设计为多态的,这就是为什么从它公开继承可能被视为一件相当奇怪的事情的原因
如果您是在不同的范例中设计代码,比如模板元编程一(TMP),那么公共继承可能是一件非常有效的事情。你看,在TMP中,公共继承服务于一个完全不同的目的,甚至与多态性和关系无关
换句话说,如果不考虑全局,就无法对你的问题给出具体的答案。在任何情况下,都要小心“机械”答案
int main()
{
std::vector<int>* vecPtr = new CMyVect();
delete vecPtr; // invokes vector constructor only, not yours
}