构造函数不适用于从 std::string 继承的类

发布于 2024-07-14 04:00:35 字数 347 浏览 3 评论 0原文

但是

#include <string>

class MyString : public std::string 
{
 public:    
   MyString() {}
};

下面的用法:

MyString s = "Happy day";
MyString s("Happy Day");
MyString s = (MyString)"Happy day";

它们都不起作用。

似乎与构造函数/运算符声明/重写有关,但是任何人都可以帮助指出我在哪里可以找到这些资源吗?

谢谢。

when doing

#include <string>

class MyString : public std::string 
{
 public:    
   MyString() {}
};

But the usage below:

MyString s = "Happy day";
MyString s("Happy Day");
MyString s = (MyString)"Happy day";

neither of them works.

It seems that there's something to do with constructors/operators declaration/overridding, but can anyone help point out where may I find these resources?

Thanks.

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

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

发布评论

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

评论(6

李白 2024-07-21 04:00:35

std::string 不是为继承而设计的。 它没有任何虚拟函数(甚至没有析构函数!),因此您无法覆盖任何内容。 它也没有受保护的接口,因此您无法从子类化中获得任何东西,而这是通过创建一些采用 std::string 的独立实用程序函数无法获得的。

请记住,大多数 STL 实现都希望您将 std::string 与复制语义一起使用,而不是引用语义,这使得添加继承字段或覆盖函数的情况变得更弱。

如果您确实想要具有额外功能的std::string之类的东西,您可以考虑使用组合而不是继承,但这也不是很好。 您不必担心 std::string 析构函数没有被正确调用,但您最终不得不包装 std::string 中的许多方法你需要的,这很乏味。 此外,当大多数代码需要 std::string 时,您的实用函数只能与 MyString 一起使用,因此它的可重用性不太好。

您最好创建一些采用 std::string 的实用函数。 或者,如果 std::string 没有提供您需要的内容,您应该使用一些其他适合您需要的字符串实现。 以下是我想到的一些可能性:

std::string isn't designed for inheritance. It doesn't have any virtual functions (not even the destructor!), so you can't override anything. It also doesn't have a protected interface, so you gain nothing from subclassing that you couldn't get by making some standalone utility functions that take std::string.

Keep in mind that most STL implementations expect you to use std::string with copy semantics, not reference semantics, and this makes the case for adding inherited fields or overriding functions even weaker.

If you really want something like std::string with extra functions, you could consider using composition instead of inheritance, but this isn't great either. You don't have to worry about the std::string destructor not getting called properly, but you do end up having to wrap a lot of methods from std::string that you need, which is tedious. Also, your utility functions will only work with MyString when most code is going to expect std::string, so it isn't very reusable.

You're better off making some utility functions that take std::string. Or, if std::string isn't providing what you need, you should go with some other string implementation that suits your needs. Here are some possibilities that come to mind:

云淡风轻 2024-07-21 04:00:35

您需要为您希望能够转换为字符串的不同类型定义一些构造函数。 这些构造函数基本上可以将参数传递给底层的 std::string 。

如果您不手动创建它们,编译器会为您创建一个默认构造函数和一个复制构造函数:

MyString() : std::string() { }
MyString(const MyString &other) : std::string(other) { }

要允许从字符串文字进行构造,您需要一个采用 const char* 的构造函数:

MyString(const char* other) : std::string(other) { }

构造函数使用 const std::string& 也可用于将 std::string 转换为字符串类型。 如果你想避免普通字符串的隐式转换,你应该将其设为显式:(

explicit MyString(const std::string &other) : std::string(other) { }

已编辑,因为我的原始版本充满了错误,我无法删除已接受的答案)

You need to define some constructors for the different types that you want to be able to convert into your strings. These constructors can basically just hand the parameters through to the underlying std::string.

If you don't manually create them, the compiler creates a default- and a copy-constructor for you:

MyString() : std::string() { }
MyString(const MyString &other) : std::string(other) { }

To allow construction from string literals, you need a constructor that takes a const char*:

MyString(const char* other) : std::string(other) { }

A constructor that takes a const std::string& would also be useful to convert std::strings to your string type. If you want to avoid implicit conversions of normal strings, you should make it explicit:

explicit MyString(const std::string &other) : std::string(other) { }

(Edited because my original version was full of errors and I can't delete the accepted answer)

活雷疯 2024-07-21 04:00:35

最重要的是你不应该这样做。 std::string 上的析构函数不是虚拟的。 这意味着,如果您执行以下操作:

std::vector<std::string*> s_vector;
s_vector.push_back(new MyString("Hello"));
s_vector.push_back(new std::string("World"));

const std::vector<std::string*>::iterator s_vector_end = s_vector.end();
std::vector<std::string*>::iterator s = s_vector.begin();
for (; s != s_vector_end; ++s)
{
    delete *s; // Error, MyString's destructor will
               // not be called, but std::string's!
}

唯一安全的方法是不向字符串添加成员。 你可能认为你现在不需要任何东西,但是稍后可能会有不知道这些问题的人(或者你,当你可能忘记了这个建议时)添加一个,然后嘿,很快,你就有了很难追踪内存泄漏。

The bottom line is that you shouldn't do this. The destructor on std::string isn't virtual. This means that if you do the following:

std::vector<std::string*> s_vector;
s_vector.push_back(new MyString("Hello"));
s_vector.push_back(new std::string("World"));

const std::vector<std::string*>::iterator s_vector_end = s_vector.end();
std::vector<std::string*>::iterator s = s_vector.begin();
for (; s != s_vector_end; ++s)
{
    delete *s; // Error, MyString's destructor will
               // not be called, but std::string's!
}

The only way this might be safe is if you don't add members to your string. You might think that you don't need any now, but someone who isn't aware of these issue may come along later (or you, when you've forgotten this advice perhaps) and add one, and then hey presto, you have a difficult to track down memory leak.

骷髅 2024-07-21 04:00:35

问题是您需要重载采用 const char* 的构造函数并调用基类构造函数,如下所示:

class MyString : public std::string {
   public:    
      MyString() {}
      MyString( const char* c ) : std::string( c )  {}
};

然后您的所有三个测试都应该起作用。

The problem is that you need to overload the constructor that takes const char* and call the base class constructor as follows:

class MyString : public std::string {
   public:    
      MyString() {}
      MyString( const char* c ) : std::string( c )  {}
};

All three of your tests should work then.

ゝ杯具 2024-07-21 04:00:35

std::string 不打算继承。 它没有任何虚拟方法,因此您无法重写它的任何方法。

你应该研究一下构图。 或者只是创建对 std::strings 进行操作的实用函数

std::string isn't intended to be inherited from. It doesn't have any virtual methods so you can't override any of its methods.

You should look into composition. Or simply creating utility functions which operate on std::strings

黒涩兲箜 2024-07-21 04:00:35

您正在定义一个不带参数的构造函数 MyString。 如果覆盖其他 ctor,那么根本没有 ctor 接受字符串参数。

您需要构造一个 const char * 类型的参数,类似于

 MyString(const char * s): std::string(s){}

(不要相信语法,查找它;我不再每天都编写 C++。)

检查该部分关于 ctor 的 C++ FAQ Lite

(哎呀。Const char *,而不是字符串。告诉你我不是每天都写 C++。)

You're defining a ctor MyString that takes no arguments. If overrides the other ctors, so there's no ctor taking a string argument at all.

You need to ctor of one argument of type const char *, something like

 MyString(const char * s): std::string(s){}

(Don't trust the syntax, look it up; I don't write C++ every day any longer.)

Check the section in the C++ FAQ Lite on ctors.

(Oops. Const char *, not string. Told you I didn't write C++ every day.)

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