0

I have this code sample in which I try to concatenate strings:

const char* NameErrorException::what() const throw()
{
    return "NameError : name '" + _name + "' is not defined";
}

Why cant I create a char* by use of + between strings?

jotasi
  • 5,077
  • 2
  • 29
  • 51
rf tg
  • 21
  • 2
  • http://stackoverflow.com/questions/662918/how-do-i-concatenate-multiple-c-strings-on-one-line – izlin Dec 14 '16 at 12:34
  • 1
    You can't use + to concatenate them. Either use `strcat` or the more safe way `snprintf`. Actually, just use `std::string`. – Hatted Rooster Dec 14 '16 at 12:34
  • 3
    because C++ is not Java (this is by far, the best answer here) – David Haim Dec 14 '16 at 12:34
  • @DavidHaim At least you said so yourself. – Hatted Rooster Dec 14 '16 at 12:36
  • @GillBates I'm kidding, but seriously, usually when new developers ask about why something is not possible in C++, they usually mean "In Java/C#/Python it is possible, how come it's impossible in C++?". this question is probably one of these – David Haim Dec 14 '16 at 12:37
  • @DavidHaim mhm, to be honest, since everyone places C++ next to those languages in terms of "levelness" (high-level, low-level etc). `const char*` should be banned. – Hatted Rooster Dec 14 '16 at 12:38
  • @GillBates perhapse, if we were to redesign C++ from scratch in modern point of view. – David Haim Dec 14 '16 at 12:40
  • @DavidHaim we'd use `std::string` literals `"yada yada"s`, which behave as expected :) – StoryTeller - Unslander Monica Dec 14 '16 at 12:42
  • @GillBates Not necessarily banned, just because it's there you don't have to use it. That's like saying to get rid of pointers in favour of smart pointers, or manual memory management because it's hard. You'd end up with Java and then we'd all be in trouble. – Colin Dec 14 '16 at 12:43
  • @Colin__s Banned in classes, banned to teach new programmers to return a bare `const char*`. – Hatted Rooster Dec 14 '16 at 12:44
  • 3
    @GillBates Yes. Institutions should start teaching modern C++, that I agree with. – Colin Dec 14 '16 at 12:45
  • 2
    Or they could teach C and assembler before teaching C++, so that programmers actually have a clue about what they are doing. Now if there existed a language with was sane, compiled and fast at the same time, we wouldn't need C or C++ at all... For now, we'll just have to settle for compiled and fast. – Lundin Dec 14 '16 at 12:49
  • @GillBates: Please note that this is an overload of `std::exception::what` which is defined to return a char*. – Martin Bonner supports Monica Dec 14 '16 at 13:02

4 Answers4

6

"Sesame Street 3" plus 4 houses ahead means "Sesame Street 7".

but what does "Sesame Street 3" plus "Sesame Street 4" means?
it means nothing.
you can add a house-offset to a street address, but what does it even mean to add two street addresses together? it makes no sense. "Sesame Street 3" plus "Sesame Street 4" IS NOT "Sesame Street 7".

const char* is a location of a character on the RAM. adding yet another location will not create new string. it is meaningless. just like adding two street addresses will not create a new street address (or a new street, for that example).

const char* is (usually) C-String. it knows nothing about string concatenation, splitting, removing or replacing. it's just the location of the first character on the RAM. this is why usually, in C++ we do use std::string. std::string is an object with behaviour. it DOES know about actions like concatenation, splitting, removing or replacing.

David Haim
  • 25,446
  • 3
  • 44
  • 78
2

A char * is a pointer to a char. The + operator can be used to add an offset to a pointer, not concatenate c strings.

Colin
  • 3,394
  • 1
  • 21
  • 29
  • 2
    You can add an integer and a pointer, but not two pointers. A nitpick, but terse answers require precise wording. – Quentin Dec 14 '16 at 12:51
  • 1
    "For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type." Which is why this won't compile. – Lundin Dec 14 '16 at 12:53
  • @Colin__s - see David Haim's "Sesame Street" answer for a good explanation – Allison Lock Dec 14 '16 at 12:53
2

The first part of this is simple: You can't add char * variables with + because C++ is not Java (or Python, or C#).

You may have learnt that "const char* represents a string in C++". This is true as far as it goes, but if you use const char* like that, you have all the responsibility of allocating and freeing memory at the right time.

In general, you are much better off using std::string to represent a string. It is safe to return a std::string from your function - it is not safe to return a const char* (who is responsible for freeing the memory)?

However, there is one exception to that rule: When you are overriding std::exception::what() - which is defined to return a const char*. The fix is that you need an additional (std::string) member of NameErrorException which you construct at the same time as you construct _name, and which you set to the full error message, and then what just returns _what_error.c_str(). So the full class would look something like:

class NameErrorException : public std::runtime_error
{
    std::string _name;
    std::string _what_error;
    std::string build_error(const std::string &name)
    {
        // Use std::string literals.
        return "NameError : name '"s + name + "' is not defined"s;
    }
public:
    NameErrorException(const std::string& name) 
    : _name(name)
    , _what_error(build_error(name))
    {}

    const char* what() const throw() override
    {
        return _what_error.c_str();
    }
}

If you don't have std::string literals, you will have to make build_error be:

        return std::string("NameError : name '") + name + "' is not defined"s;
  • I think there is an overload for `operator+` with pointers and strings in any order, so one normal string is enough when concatenating multiple strings. It's normally the first operand, but second is good too. – anatolyg Dec 14 '16 at 13:17
-1

You get the error because operator+ is not used for concatenation of c-strings. operator+ is only defined for adding index values to pointers.

You can fix this by creating an std::string object inside the NameErrorException object and initializing it when the exception is created (i.e. in the constructor):

class NameErrorException : public std::runtime_error {
private:
    std::string _errorString;  // Used to store the error message.

public:
    // Constructor.
    NameErrorException(const char * const name) {
        _errorString.append("NameError : name '");
        _errorString.append(name);
        _errorString.append("' is not defined");
    }

    virtual const char * what() {
        return _errorString.c_str();
    }
};

Alternatively, you can create a second const char * buffer that is the correct size, and use std::snprintf() or std::strncat() to create the string. (Remember to clean up the new buffer inside your destructor!)

Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65