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

时间:2009-02-17 05:28:43

标签: c++ stl

做的时候

#include <string>

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

但是下面的用法:

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

它们都不起作用。

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

感谢。

6 个答案:

答案 0 :(得分:35)

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

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

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

你最好制作一些带std::string的实用功能。或者,如果std::string未提供您所需的内容,则应该使用其他符合您需求的字符串实现。以下是一些可能的想法:

答案 1 :(得分:6)

您需要为希望能够转换为字符串的不同类型定义一些构造函数。这些构造函数基本上只需将参数传递给基础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

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

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

答案 2 :(得分:4)

最重要的是你不应该这样做。 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!
}

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

答案 3 :(得分:3)

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

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

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

答案 4 :(得分:3)

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

你应该研究一下作文。或者只是创建在std :: strings

上运行的实用程序函数

答案 5 :(得分:1)

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

您需要使用const char *类型的一个参数,例如

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

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

检查C++ FAQ Lite on ctors

中的部分

(糟糕.Cons char *,不是字符串。告诉你我每天都没有写C ++。)