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

发布于 2024-08-13 05:55:19 字数 878 浏览 3 评论 0原文

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

The class std::wstring is missing some operations for "normal" c strings (and literals).

I would like to add these missing operations in my own custom class:

#include <string>

class CustomWString : public std::wstring {

        public:

            CustomWString(const char*);
            const char* c_str(void);
};

The code above compiles fine on Ubuntu Karmic with g++ v4.4.1.

But I am wondering if there are arguments against doing so?

EDIT: some examples to clarify what I mean with "missing operations" :

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;

EDIT: I would like to have this somehow "centralized". That's because I have a project to be ported from M$-Windows with thousand's of these failing operations.

The nice thing is: there is one central place where the string type to be used is defined, e.g.:

#ifdef WINDOWS_OS
    typedef std::wstring AppStringClass;
#else
    typedef std::string AppStringClass;
#endif

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

无力看清 2024-08-20 05:55:19

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

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

您就有未定义的行为。

It is legal, but many people think it undesirable. The issue is that the standard library template classes do not have virtual destructors. So if you ever write code like this:

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

you have undefined behaviour.

蹲在坟头点根烟 2024-08-20 05:55:19

编译器肯定允许你这样做,因为在 C++ 中没有办法用公共构造函数来密封类。

STL 容器不是为继承而设计的,因此这通常是一个坏主意。 C++ 有许多奇怪的角落需要忽略这一点。您的派生类可能会因另一个 STL 实现而中断,或者只是因构建环境的更新而中断。

然而,我认为这是一个强烈的警告信号,而不是完全禁止。这是一个“你真的确定你在做什么吗?你知道所有的影响吗?并且对所有替代方案都有充分的论据”?

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

但是我不确定您要如何实现char const * c_str()< /code> 也不提供字符串存储。一旦引入新的数据成员,您就进入了一个充满地雷的领域。

The compiler definitely lets you, as there is no way to seal a class with a public constructor in C++.

STL containers are not designed for inheritance, so it's generally a bad idea. C++ has to many strange corners to ignore that. Your derived class might break with another STL implementation, or just with an update of the build environment.

However, I'd consider it a striong warning sign, not a total no-go. It's a "are you really really sure what you are doing, do you know all implications, and have good arguments against all alternatives"?

In your case: Providing additional constructors is fine (since the public interface is documented and you can replicate that), and as long as you are not introducing new data members or a VMT, slicing or non-virtual destructor is not a problem. (Keep in mind though that the C++ standard claim undefined behavior when deleting through a base class pointer without virtual DTor)

However I am not sure how you want to implement char const * c_str() without also providing storage for the string. And as soon as you introduce new data members, you are entering a field of landmines.

甜宝宝 2024-08-20 05:55:19

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

所以,以下是危险的:

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

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

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

I think you know that basic_string doesn't define a virtual destructor. It is WRONG to use wstring in a polymorphic manner. Otherwise, you can use your custom class as usual.

So, the following is hazardous:

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

Using your custom class directly is OK, e.g.

vector<CustomWString> mystrings; // OK
mystrings.push_back("...");
(り薆情海 2024-08-20 05:55:19

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

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

     ~CMyVect()
     {
        delete someMemory;
     }
  };

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

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

这并不是说您不能从这些对象继承,但它可能会带来这个问题。您必须小心如何使用您继承的对象,或者只是不需要触发析构函数(不要持有任何需要释放的资源)。

The traditional argument against inheriting from STL objects is they do not have a virtual destructor. So, take vector for example. If I were to inherit from it:

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

     ~CMyVect()
     {
        delete someMemory;
     }
  };

The non virtual destructor in the base class means that if the user of this points a ponter-to-vector-of-ints to a CMyVect then deletes that pointer, your destructor will not be invoked, leaking memory. That is to say:

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

So that's not to say you can't inherit from these objects, but it can be frought with this problem. You have to be careful how you use the objects you are inheriting from or alternatively j ust have no need for your destructor to fire (don't hold any resources that need to be freed).

意中人 2024-08-20 05:55:19

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

此外,添加这些特定函数似乎是一个坏主意,因为它们依赖于语言环境和编码。你给班级赋予了不止一项责任。 charwchar_t 之间转换的功能属于其他地方。

It is possible, and legal. But it's a bad idea. The classes are not designed for inheritance, and extending them is best done without inheritance. If you are not careful when using the classes, you'll get undefined behavior. (The classes don't have virtual destructors)

Moreover, it seems a bad idea to add those specific functions, since they depend on locale and encoding. You're giving the class more than one responsibility. The functionality of converting between char and wchar_t belongs elsewhere.

长安忆 2024-08-20 05:55:19

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

The class template std::basic_string (of which std::wstring is a typedef with specific template arguments) does not have a virtual destructor, and as such, inheriting from it publicly is a bad idea.

二手情话 2024-08-20 05:55:19

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

You can do it. But I see no point, since std::basic_string
(and its concrete versions std::string and std::wstring)
define no virtual methods and have non-virtual destructor.
So there is no way, you can use your subclass properly in place of e.g. std::wstring.

人事已非 2024-08-20 05:55:19

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

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

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

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

换句话说,如果不考虑大局,就无法为您的问题提供具体答案。无论如何,请注意“机械”答案,例如“由于 std::wstring 没有虚拟析构函数,因此您不能继承它,因为它会破坏<继续说明代码>”。即使在 OOP 方法中,这种推理也是完全错误的。

The ability to "inherit" one class from another is a language feature. It is just a formal, plain and dry language feature that is not tied to any specific aplication or any specific use model. It is a low-level tool that you can use for different purposes. And, to answer your question, it is perfectly legal to inherit from std::wstring class.

However, the next question would be the question of "why". Why do you want to inherit from std::wstring?

If you are designing your code within the OOP paradigm, then inheriting publicly from std::wstring might not be a good idea, "might" being a key word here. Public inheritance in OOP usually implies an IS-A relationship in a polymorphic class hierarchy. Class std::wstring is not designed to be polymorphic, which is the reason why publicly inheriting from it might be seen as a rather strange thing to do.

If you are designing your code within a different paradigm, like for example template meta-programming one(TMP), then public inheritance might be a perfectly valid thing to do. You see, in TMP public inheritance serves a completely different purpose, not even remotely related to polymorphism and relationships.

In other words, there no way to produce a concrete answer to your question without taking into account the bigger picture. In any case, beware of "mechanical" answers, like "since std::wstring has no virtual destructor, you can't inherit from it since it will break <proceed to illustrate with code>". Such reasoning is completely bogus, even within the OOP approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文