0

I have a derived class called Mystring that is derived from std::string, and I would like to set the value of the string that I am working with.

From my understanding to access the string object from std::string I would use *this to get the string that I am currently working with.

I would like to set *this to a string of my choosing, I did this my setting *this = n; but it crashes my code and returns a "Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)" my code is below:

So my question is, how can I set the value of std::string to something through my derived class. Much thanks!

class Mystring : public std::string
{
public:
    Mystring(std::string n);
    std::string removePunctuation();
    std::string toLower();


};
Mystring::Mystring(std::string n)
{
    *this = n;
}
std::string Mystring::removePunctuation()
{
    long int L = length();

    char *cstr = new char[L + 1];
    strcpy(cstr, c_str());
    //cout << cstr[L-1] << endl; // last character of c string
    if(!isalpha(cstr[L-1]))
    {
        pop_back() ;
    }

    return *this;
}
std::string Mystring::toLower()
{

    long int L = length();

    char *cstr = new char[L + 1];
    strcpy(cstr, c_str());

    for(int i = 0; i < L;i++)
    {
        int buffer = cstr[i];
        cstr[i] = tolower(buffer);
        std::cout << cstr[i];


    }
    std::string returnstring(cstr);
    delete [] cstr;

    return returnstring;
}
int main() {
    Mystring temp("dog");
    std::cout << "Hello World";
    return 0;
}
  • 4
    Why are you subclassing `std::string` just for a couple of convenience functions that are essentially one-liners? – Colin Basnett Mar 06 '18 at 20:49
  • 5
    Don't do this. `std::string` is not intended to be used as a base class. It contains no virtual functions you can override, and it doesn't have a virtual destructor. Lacking that, a publicly derived class introduces substantial danger while providing no benefit. – Jerry Coffin Mar 06 '18 at 20:51
  • You're deep in the danger zone here. Eject! These are just static functions, presenter functions technically. – tadman Mar 06 '18 at 20:54
  • Good explanation here: https://stackoverflow.com/questions/6806173/subclass-inherit-standard-containers – Robinson Mar 06 '18 at 20:54
  • Watch this talk: **[Free your functions](https://www.youtube.com/watch?v=WLDT1lDOsb4)** – rustyx Mar 06 '18 at 21:00
  • If `*this = n` were really responsible for crashing your code then you would remove those utility functions that you don't even invoke as they are just noise. – Lightness Races in Orbit Mar 06 '18 at 21:09
  • Why not directly initialize the base, e.g. `MyString(std::string n) : std::string{n}`? – xskxzr Mar 07 '18 at 08:54

2 Answers2

3

Style aside, the fundamental idea of using an assignment operator to "reset" an inherited subobject is not necessarily incorrect.

However, a conversion is required to get from std::string (the type of the RHS) to Mystring (the type of the LHS, i.e. *this). The only way to perform that conversion is to use the constructor Mystring(std::string). Except… you're already in it. Hence that function is effectively recursive and will repeat forever until you exhaust your stack.

Stack filling up

You need to upcast *this to a std::string in order to make this work:

static_cast<std::string&>(*this) = n;

I do agree with the other people here that you shouldn't be deriving from std::string, and certainly not just to add a couple of utility functions that ought to be free functions taking std::string (perhaps in a nice namespace, though?).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

Don't do it. Derivation provides no benefit in this situation.

Create your added functions as free functions that operate on a string. For example:

void remove_punctuation(std::string &s) { 
    if (!std::isalpha(s.back()))
        s.pop_back();
}

void tolower(std::string &s) { 
    for (auto &c : s)
        c = std::tolower(c);
}

Making either/both of these a member function serves no purpose and provides no benefit.

References

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111