user216085
user216085

Reputation: 61

C++ plus operator not working with const char and others

Hello i made a variable storage like string and this is the source

class str
{
private:

    const char * _mystring;

public:

    // Using this function to made new str
    str(const char * _str) { _mystring = _str; }

    // Get the content of this str
    const char * read() { return _mystring; }

    // Get the content in char *
    char * read_c() { return strdup(_mystring); }

    // Operator for equal action with extern const char
    str & operator = (const char * _str) { _mystring = _str; return *this; }

    // Operator for equal action with extern str storage
    str & operator = (str _str) { _mystring = _str.read(); return *this; }

    // Operator for add action
    str operator + (const char * _str) {
        return str(strcat(read_c(), _str));
    }

    // Operator for add action with new str
    str operator + (str & _str) {
        return str(strcat(read_c(), _str.read()));
    }
};

and this is my test program

int main() {

    str var1("Var1"); // No problem
    str var2("Var2"); // No problem

    str var3 = var1 + var2;  // No problem
    str var4 = var1 + "tempStr"; // I got runtime error !
    str var5 = "tempStr" + var2; // I got error before compile

    cout << var1.read() << endl;
    cout << var2.read() << endl;
    cout << var3.read() << endl;
    cout << var4.read() << endl;

    return 0;
}

what is the problem that i can't create something like var3 and var4 and i got error (i get error while i want to merge const char with my str ... i set + operator but there is problem for when i want to merge const char with my str (not my str with const char... on this action, there is no problem) but wait i got error (debug (close program)) after compile and print var7 too !

Upvotes: 1

Views: 3974

Answers (4)

Etherealone
Etherealone

Reputation: 3558

For str var3 = "tempTxt0" + "tempTxt1" + "tempTxt2"; // Error:

This does not work because the compiler sees these types (omitting variable names): str = const char* + const char* + const char *. Adding char pointers together is not what you want. However, if you only had one of them to be type of class str, it would work. E.g. str = str(const char*) + const char* + const char * would call the str::operator+, which returns a new object of type str and the rest will follow the same way.

For str var4 = "tempTxt3" + var1; // Error:

This does not work because you declare operator+ as a member function. Again compiler sees these types (omitting variable names): str = const char* + str. There is no operator+ declared for const char* as the first operand and str as the second operand. You have a member operator+ but that operator works on a class str so you would need a class str on the left hand side; as in str + const char*. Think of it like a function call because it is exactly a member function call. It is the same as typing str = str.operator+("text"). Now you see, str = "text".operator+(str) does not work because it does not exist.

If you declared a non-member function str operator+(const char* first, const str& second);, it would work. The compiler will look for operators that matches what you want in outer namespace scopes of the parameters up to the global scope (this is called ADL). But there is a better way:

Declare str operator+(const str& lhs, const str& rhs);. If you declare your operators this way in the namespace scope of the class str, then compiler will use ADL (on Wikipedia) using the second argument's type (which is class str) and find this operator. Then, the compiler can see that class str has a non-explicit constructor which can take const char*: str(const char * str). It can then create a temporary object of class str and use the operator+ you defined.

So for your example, as you do not have any namespaces, you would need this at its simplest (notice I have added a few const keywords):

class str
{
private:

    const char * _mystring;

public:

    // Using this function to made new str
    str(const char * _str) { _mystring = _str; }

    // Get the content of this str
    const char * read() const { return _mystring; }

    // Get the content in char *
    char * read_c() const { return strdup(_mystring); }

    // Operator for equal action with extern const char
    str & operator = (const char * _str) { _mystring = _str; return *this; }

    // Operator for equal action with extern str storage
    str & operator = (str _str) { _mystring = _str.read(); return *this; }
};

// Operator for add action with new str
str operator+ (const str& lhs, const str& rhs) {
    return str(strcat(lhs.read_c(), rhs.read()));
}

P.S. Your example has more problems. read_c duplicates the string (let say) of 10 bytes and you concatenate more bytes at the end of it. That is an overflow because your duplicated buffer is 10 bytes. You have to allocate and free the memory properly but that is for another question I guess. E.g.

str operator+(const str& lhs, const str& rhs) {
  const std::size_t ls = lhs.size();
  const std::size_t rs = rhs.size();
  char* n = new char[ls + rs + 1];
  std::memcpy(n, lhs.read(), ls);
  std::memcpy(n + ls, rhs.read(), rs);
  n[ls + rs] = '\0';
  return str(n);
}

Then you still have the problem of when to delete.

Upvotes: 3

Sly_TheKing
Sly_TheKing

Reputation: 528

str var3 = "tempTxt0" + "tempTxt1" + "tempTxt2"; // Error
str var4 = "tempTxt3" + var1; // Error

In these lines you're trying to add 2 pointers to some static memory (in other words your operator isn't called)

On the left side of the operator plus needs to be your class

Having an empty (only with \0) instance of your class will fix your error (as you might have already noted):

str var4 = str("") + "tempTxt3" + var1; //now it is okay

Also, note that strcat doesn't allocate memory for concatening, you have to do it with realloc yourself

Upvotes: 3

marcinj
marcinj

Reputation: 49986

str var4 = var1 + "tempStr"; // I got runtime error !

in this case following operator+ overload is called:

str operator + (const char * _str) {
    return str(strcat(read_c(), _str));
}

you call strcat on a pointer which points to a buffer not large enough to contain both current string and _str. The fastest solution is to use std::string, otherwise you need to allocate large enough buffer and also remember to keep care of its lifetime (adhere to rule of three etc.)

str var5 = "tempStr" + var2; // I got error before compile

You need a global operator overload of following signature:

str operator + (const char * _str, const str& s);

Upvotes: 0

dbush
dbush

Reputation: 223972

When you override a binary operator such as +, the left operand has to be the object in question. The reason you get errors is because the left operand is a string constant and this the default + is used.

You need to create friend functions for these operators that accept a const char * for the first parameter and either str or a const char * for the second parameter.

Upvotes: 2

Related Questions