I want to extend the C++ string class, returning subclass references (instead of parent st开发者_如何学JAVAring reference), but this code excerpt...
#include <string>
using namespace std;
class mystring : public string
{
public:
mystring& left( int cnt )
{ return (mystring&)mystring( substr(0,cnt) );
}
};
produces this VS8 compiler error:
error C2440: '' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'mystring'
What's the right way to declare mystring::left() so the compiler will stop complaining, hopefully also eliminating the cast?
error C2440: '' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'mystring'
From MSDN page on C2440:
C2440 can also occur for an incorrect use of a user-defined conversion. For more information on user-defined conversions, see User-Defined Conversions). The following sample generates C2440.
The error you hit is because you are trying to return a base class object via a reference to an object of the derived class. It works the other way well. Hence, your need for the cast -- which is bad.
Standard containers (including std::string
) are not suitable for inheritance, use aggregation instead.
You don't need the cast to string&
.
Try something like this:
#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;
};
The problem seems to be that substr
returns a std::string
, not an instance of your subclass. Do you have a mystring::mystring(const std::string&)
constructor?
And why on earth are you subclassing std::string anyway? :D
It's probably better to write a free function instead of subclassing.
#include <string>
namespace mystring {
std::string left(const std::string& str, int cnt)
{
return str.substr(0,cnt);
}
}
be careful when deriving from a class in the std namespace.
see permalink to answer for my own question from peterchen.
EDIT: the essence of the article referenced by the permalink is: you can derive from std::string. But you should not introduce a new member variable.
The compiler already tells you what the problem is - it can't convert from std::string
to mystring
as your class isn't constructible from std::string
.
You shouldn't subclass the standard libraries types however, they aren't suited for that - use composition.
If we leave that issue aside for a moment:
You need to supply a constructor that takes a std::string
. But that still leaves a problem: you're returning a reference to a temporary - just return by value here.
Your class could now look like this:
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);
}
};
精彩评论