开发者

right way to return new instances from subclass of C++ string

开发者 https://www.devze.com 2022-12-15 05:01 出处:网络
I want to extend the C++ string class, returning subclass references (instead of parent st开发者_如何学JAVAring reference), but this code excerpt...

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);
    }
};
0

精彩评论

暂无评论...
验证码 换一张
取 消