繁体   English   中英

是否允许从std名称空间(即std :: wstring)中的类继承?

[英]Is it allowed to inherit from a class in the std namespace (namely std::wstring)?

类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

这是合法的,但许多人认为这是不可取的。 问题是标准库模板类没有虚拟析构函数。 因此,如果您曾经编写过这样的代码:

std::wstring * p = new CustomWString ;
...
delete p;

您有不确定的行为。

编译器绝对可以让您使用,因为无法用C ++中的公共构造函数来密封类。

STL容器不是为继承而设计的 ,因此通常不是一个好主意。 C ++有很多奇怪的地方可以忽略。 您的派生类可能会因其他STL实现而中断,或者仅随着构建环境的更新而中断。

但是,我认为这是一个强烈的警告信号,而不是完全不执行。 这是“您是否真的确定自己在做什么,是否了解所有含义并针对所有替代方案都拥有很好的论据”?

在您的情况下:提供额外的构造函数就可以了(因为已经记录了公共接口,并且您可以复制它),并且只要不引入新的数据成员或VMT,切片或非虚拟的析构函数都不会出现问题。 (请记住,当通过不带虚拟DTor的基类指针删除时,C ++标准声明了未定义的行为)

但是我不确定如何在不提供字符串存储的情况下实现char const * c_str() 并且,一旦您引入了新的数据成员,您就会进入一个地雷领域。

我想您知道basic_string并未定义虚拟析构函数。 多态方式使用wstring是错误的。 否则,您可以照常使用自定义类。

因此,以下是危险的:

vector<wstring*> mystrings;
mystrings.push_back(new CustomWString);
...
delete mystrings[0]; // No virtual destructor

直接使用您的自定义类是可以的,例如

vector<CustomWString> mystrings; // OK
mystrings.push_back("...");

反对从STL对象继承的传统说法是它们没有虚拟析构函数。 因此,以矢量为例。 如果我要继承它:

  class CMyVect : public std::vector<int>
  {
      ...
     int* someMemory;
  public:
     CMyVect()
     {
        someMemory = new int();
     }

     ~CMyVect()
     {
        delete someMemory;
     }
  };

基类中的非虚拟析构函数意味着,如果该用户将int的ponter-to-vector-ofs指向CMyVect,然后删除该指针,则不会调用您的析构函数,从而导致内存泄漏。 也就是说:

 int main()
 {
     std::vector<int>* vecPtr = new CMyVect();
     delete vecPtr; // invokes vector constructor only, not yours
 }

因此,这并不是说您不能从这些对象继承,但是可能会遇到这个问题。 您必须小心如何使用从中继承的对象,或者根本不需要触发析构函数(不需要保存任何需要释放的资源)。

这是可能的,而且合法。 但这是一个坏主意。 这些类不是为继承而设计的,最好在没有继承的情况下扩展它们。 如果您在使用类时不小心,则会得到未定义的行为。 (这些类没有虚拟析构函数)

而且,添加这些特定功能似乎是个坏主意,因为它们取决于语言环境和编码。 您不仅要给全班提供一项责任。 charwchar_t之间转换的功能在其他地方。

类模板std::basic_string (其中std::wstring是与特定的模板参数的类型定义) 没有虚析构函数,因此,从它继承公开是一个坏主意

你能行的。 但是我看不到任何意义,因为std :: basic_string(及其具体版本std :: string和std :: wstring)没有定义虚拟方法并且具有非虚拟析构函数。 因此,没有办法,您可以正确使用子类来代替例如std :: wstring。

从另一类“继承”一个类的能力是一种语言功能。 它只是一种正式,简单而干燥的语言功能,与任何特定的应用程序或任何特定的使用模型无关。 它是一个低级工具,可用于不同目的。 而且,要回答您的问题,从std::wstring类继承是完全合法的。

但是,下一个问题将是“为什么”的问题。 为什么要从std::wstring继承?

如果要在OOP范式中设计代码,则从std::wstring 公开继承可能不是一个好主意,“可能”是此处的关键词。 OOP中的公共继承通常意味着多态类层次结构中的IS-A关系。 std::wstring的设计目的不是多态的,这就是为什么从其公开继承可能被视为一件很奇怪的事情的原因。

如果要在不同的范式中设计代码,例如模板元编程模板(TMP),则公共继承可能是一件非常有效的事情。 您会看到,在TMP中,公共继承具有完全不同的目的,甚至与多态性和关系都没有太远的关系。

换句话说,如果不考虑全局,就无法对您的问题给出具体的答案。 在任何情况下,请提防“机械”答案,例如“由于std::wstring没有虚拟析构函数,因此您不能继承它,因为它会破坏<proceded to show with code> ”。 即使在OOP方法中,这种推理也是完全虚假的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM