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

时间:2022-04-27 13:17:30

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.

6 个解决方案

#1


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.

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

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

如果您不手动创建它们,编译器会为您创建一个default-和copy-constructor:

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*:

要允许从字符串文字构造,您需要一个带有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:

采用const std :: string的构造函数对于将std :: strings转换为字符串类型也很有用。如果你想避免普通字符串的隐式转换,你应该明确它:

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)

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

#2


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.

std :: string不是为继承而设计的。它没有任何虚函数(甚至不是析构函数!),所以你不能覆盖任何东西。它也没有受保护的接口,因此通过创建一些带有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.

请记住,大多数STL实现都希望您使用带有复制语义的std :: string,而不是引用语义,这样就可以添加继承字段或覆盖函数甚至更弱。

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.

如果你真的想要带有额外函数的std :: string之类的东西,你可以考虑使用组合而不是继承,但这也不是很好。你不必担心std :: string析构函数没有被正确调用,但是你最终必须从你需要的std :: string中包装很多方法,这很乏味。此外,当大多数代码期望std :: string时,您的实用程序函数仅适用于MyString,因此它不是非常可重用的。

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:

你最好制作一些带有std :: string的实用程序函数。或者,如果std :: string没有提供您需要的内容,您应该使用其他适合您需求的字符串实现。以下是一些可能的想法:

  • SGI's STL extension, std::rope. It's in GNU C++, so maybe you can rely on it.
  • SGI的STL扩展,std :: rope。它是在GNU C ++中,所以也许你可以依赖它。

  • Boost has a pretty extensive string algorithm library that lets you use concepts to specify how your string is represented.
  • Boost有一个非常广泛的字符串算法库,允许您使用概念来指定字符串的表示方式。

  • Also see this if you must "derive" from std::string
  • 如果必须从std :: string“派生”,也请看这个

#3


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 :: 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 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.

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

#4


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

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

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

All three of your tests should work then.

那么你的所有三个测试都应该有效。

#5


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.

std :: string不是要继承的。它没有任何虚拟方法,因此您无法覆盖其任何方法。

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

你应该研究一下构图。或者只是创建在std :: strings上运行的实用程序函数

#6


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.

你正在定义一个不带参数的ctor MyString。如果覆盖其他ctors,那么根本就没有ctor采用字符串参数。

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

你需要一个类型为const char *的参数的ctor,类似于

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

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

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

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

请查看C ++ FAQ Lite中有关ctors的部分。

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

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

#1


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.

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

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

如果您不手动创建它们,编译器会为您创建一个default-和copy-constructor:

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*:

要允许从字符串文字构造,您需要一个带有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:

采用const std :: string的构造函数对于将std :: strings转换为字符串类型也很有用。如果你想避免普通字符串的隐式转换,你应该明确它:

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)

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

#2


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.

std :: string不是为继承而设计的。它没有任何虚函数(甚至不是析构函数!),所以你不能覆盖任何东西。它也没有受保护的接口,因此通过创建一些带有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.

请记住,大多数STL实现都希望您使用带有复制语义的std :: string,而不是引用语义,这样就可以添加继承字段或覆盖函数甚至更弱。

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.

如果你真的想要带有额外函数的std :: string之类的东西,你可以考虑使用组合而不是继承,但这也不是很好。你不必担心std :: string析构函数没有被正确调用,但是你最终必须从你需要的std :: string中包装很多方法,这很乏味。此外,当大多数代码期望std :: string时,您的实用程序函数仅适用于MyString,因此它不是非常可重用的。

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:

你最好制作一些带有std :: string的实用程序函数。或者,如果std :: string没有提供您需要的内容,您应该使用其他适合您需求的字符串实现。以下是一些可能的想法:

  • SGI's STL extension, std::rope. It's in GNU C++, so maybe you can rely on it.
  • SGI的STL扩展,std :: rope。它是在GNU C ++中,所以也许你可以依赖它。

  • Boost has a pretty extensive string algorithm library that lets you use concepts to specify how your string is represented.
  • Boost有一个非常广泛的字符串算法库,允许您使用概念来指定字符串的表示方式。

  • Also see this if you must "derive" from std::string
  • 如果必须从std :: string“派生”,也请看这个

#3


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 :: 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 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.

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

#4


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

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

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

All three of your tests should work then.

那么你的所有三个测试都应该有效。

#5


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.

std :: string不是要继承的。它没有任何虚拟方法,因此您无法覆盖其任何方法。

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

你应该研究一下构图。或者只是创建在std :: strings上运行的实用程序函数

#6


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.

你正在定义一个不带参数的ctor MyString。如果覆盖其他ctors,那么根本就没有ctor采用字符串参数。

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

你需要一个类型为const char *的参数的ctor,类似于

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

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

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

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

请查看C ++ FAQ Lite中有关ctors的部分。

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

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