C++ 从C+;的子类返回新实例的正确方法+;一串

C++ 从C+;的子类返回新实例的正确方法+;一串,c++,C++,我想扩展C++字符串类,返回子类引用(而不是父字符串引用),但是这个代码摘录…< /p> #include <string> using namespace std; class mystring : public string { public: mystring& left( int cnt ) { return (mystring&)mystring( substr(0,cnt) ); } }; #包括 使用名称空间std; 类mystring

我想扩展C++字符串类,返回子类引用(而不是父字符串引用),但是这个代码摘录…< /p>
#include <string>
using namespace std;

class mystring : public string
{
public:
 mystring&  left( int cnt )
 {   return  (mystring&)mystring( substr(0,cnt) );
 }
};
#包括
使用名称空间std;
类mystring:公共字符串
{
公众:
mystring和left(int-cnt)
{return(mystring&)mystring(substr(0,cnt));
}
};
产生此VS8编译器错误:

错误C2440:'': 无法从转换 'std::basic_string' “我的串”


声明mystring::left()的正确方法是什么,这样编译器就不会抱怨,希望也能消除强制转换?

问题似乎是
substr
返回的是
std::string
,而不是子类的实例。您是否有
mystring::mystring(const std::string&)
构造函数

到底为什么要将std::string子类化呢D

最好编写一个自由函数,而不是子类化

#include <string>

namespace mystring {
  std::string left(const std::string& str, int cnt)
  {   
     return str.substr(0,cnt);
  }
}
#包括
名称空间mystring{
std::string left(常量std::string&str,int-cnt)
{   
返回str.substr(0,cnt);
}
}
错误C2440:'':无法从'std::basic_string'转换为'mystring'

从C2440上的MSDN页面:

C2440也可能发生在错误的 使用用户定义的转换。对于 有关用户定义的应用程序的详细信息 转换,请参见用户定义 转换)。下面的示例 生成C2440

您遇到的错误是因为您试图通过对派生类对象的引用返回基类对象。它的工作方式正好相反。因此,你需要演员阵容,这是不好的

标准容器(包括
std::string
)不适合继承,请改用聚合

您不需要强制转换为
字符串&

试着这样做:

#include <string>
using namespace std;

class mystring     {
public:
 // create an appropriate conversion op/ctor between string -> mystring
 mystring(string const& s) : impl(s) {}
 mystring  left( int cnt )
 {   
     return mystring( impl.substr(0,cnt) );
 }
 string impl;

};
class mystring  
{
    std::string m_string;
public:
    mystring(const std::string& s) : m_string(s) {}

    mystring left(std::string::size_type cnt) {
        return m_string.substr(0,cnt);
    }
};
#包括
使用名称空间std;
类mystring{
公众:
//在string->mystring之间创建适当的转换op/ctor
mystring(字符串常量&s):impl(s){}
mystring左(int cnt)
{   
返回mystring(impl.substr(0,cnt));
}
字符串impl;
};

从std命名空间中的类派生时要小心

请参见回答彼得森提出的我自己的问题


编辑:永久链接引用的文章的本质是:您可以从std::string派生。但是您不应该引入新的成员变量。

编译器已经告诉您问题所在-它不能从
std::string
转换到
mystring
,因为您的类不能从
std::string
构造

您不应该对标准库类型进行子类化,但是,它们不适合这种使用组合

如果我们暂时搁置这个问题:
您需要提供一个接受
std::string
的构造函数。但这仍然留下了一个问题:您正在返回一个对临时的引用,这里只需按值返回即可

您的类现在可以如下所示:

#include <string>
using namespace std;

class mystring     {
public:
 // create an appropriate conversion op/ctor between string -> mystring
 mystring(string const& s) : impl(s) {}
 mystring  left( int cnt )
 {   
     return mystring( impl.substr(0,cnt) );
 }
 string impl;

};
class mystring  
{
    std::string m_string;
public:
    mystring(const std::string& s) : m_string(s) {}

    mystring left(std::string::size_type cnt) {
        return m_string.substr(0,cnt);
    }
};

请解释为什么你认为你需要对这个STD::字符串这样的子类。我正在重用代码,它使用了MFC cstring,它有左、右和C++中没有找到的其他函数:String和MFC cString不兼容。最好的方法是将mfc.Left(3)这样的函数转换为Left(stds,3)这样的自由函数。聚合的问题是必须重新定义字符串的整个接口。子类化可以实现所有这些。编译器似乎很满意:mystring&left(intcnt){return(mystring&)substr(0,cnt);}为什么这些函数需要是成员?查看boost字符串库。这里的自由函数可能更好。直接举个例子,仍然给出了C2440-mystring不能从
std::string
构造,因为它没有接受std::string或它可以转换为的类型的构造函数。也许你应该注意为什么
std::string
不应该被子类化。例如,析构函数和所有那些可爱的东西。很抱歉,但我没有得到继续的投票:在问题的上下文中,它是错误的-OP试图从
std::string
构造
mystring
的实例,它不起作用,因为
mystring
不能从
std::string
@gf:Ah构造,我看到了输入错误,
left()
实现中出现了问题。然而,我指出了设计中一个更基本的缺陷。至于返回一个
mystring
——只需创建一个合适的转换操作符(我留下来做练习,应该提到)。至于upvots,我不会发表评论,但会修正你的例子。不过,你指的是C2440,这是因为另一个原因,然后你会说。+1,但删除“可能”;-)来自其他语言的C++程序员只需接受C++中的所有东西都不应该是成员函数。这是令人惊讶的难以理解的,即使您看到自由函数在中是多么有用。但在我的情况下,在我到达C++之前,我已经被Python软化了。非会员
len
可能总是让我有点抓狂。。。