2

I'm learning C++ and creating a simple class, tstring, defined by:

  • n the number of characters in a string;
  • ntotal the total number of characters in the tstring;
  • p, pointer to a zone which contains the data.

Hence, this class is composed by a static part (n, ntotal and p) and by a dynamic part (the data itself).

I created three constructors :

  • one without parameters;
  • one copy constructor;
  • one constructor which takes a C-string parameter.

I would like to be able to concatenate one tstring object with one C string, using for example the instructions :

tstring x("Hello), y;
y = x + " World";

I think I should overload the + operator. However I don't understand which way I should use to overload it between internal way :

tstring tstring::operator+(char string[])

or external way (with setter and getter methods)

tstring operator+ (const tstring& myTstring, const char* string)

Can someone explain me the difference and the best way to adopt?

Thank you in advance!

filaton
  • 2,257
  • 17
  • 27
  • possible duplicate of [Overload operators as member function or non-member (friend) function?](http://stackoverflow.com/questions/1905439/overload-operators-as-member-function-or-non-member-friend-function) – Emil Laine Feb 15 '15 at 19:57
  • For something like this, I would use "tstring tstring::operator+(char string[])" because you want access to the member variables without having to friend the operator function from the class. – thang Feb 15 '15 at 20:02
  • 1
    @thang I disagree, the issue is with calling `char[]` + `tstring`, won't work in this case (even if `char[]` is implicitly convertible to `tstring`, it won't be converted as it appears on the left hand side). I think it's a good rule of thumb to declare the binary operators as friends. – vsoftco Feb 15 '15 at 20:05
  • @vsoftco, but "tstring operator+ (const tstring& myTstring, const char* string)" won't solve that problem, but now you have to add that operator+ function as a friend. – thang Feb 15 '15 at 20:11
  • What I'd do is declare an implicit constructor that converts `char[]` to `tstring`, i.e. `tstring::tstring(char[])`, then simply define `operator+(tstring, tstring)` as a friend. There's nothing wrong with having it as a friend, it doesn't break encapsulation more than the member function, and it definitely makes life a bit easier. – vsoftco Feb 15 '15 at 20:17
  • @vsoftco, that works, too, but the constructor probably does a new and a memcpy (and subsequently delete in the destructor). now you're copying the initial portion twice. once in the constructor and once when + happens. consider this code: tstring x = ""; for (int i = 0; i < 1000; i++) { x = "hello " + x; } (or something to that effect) – thang Feb 15 '15 at 20:23
  • @thang well yes, if one cares so much about efficiency, one can declare a move constructor, so the rvalue `tstring(char[])` is moved ;) – vsoftco Feb 15 '15 at 20:32
  • @vsoftco, how does that solve the current problem? move constructor won't remove the memcpy from string literal into a temporary memory before +. – thang Feb 15 '15 at 20:36
  • @thang define `operator+(tstring&&, tstring&&)`, I didn't go in more details, but overall it's a matter of preference. In general though, when one doesn't deal with this kind of resource acquisition situation, I still thing the `friend` approach is the way to go. Maybe I should give this problem a try, as it seems a nice exercise :) – vsoftco Feb 15 '15 at 20:38
  • @vsoftco, still doesn't remove the literal to tstring conversion. an advantage of having a separate operator+ for const char* as in esesen's answer is that the literal on the lhs gets copied only once. – thang Feb 15 '15 at 20:40
  • @thang, yes, I agree here, you're right. For string literals you're stuck. – vsoftco Feb 15 '15 at 20:41

1 Answers1

1

In this case, you probably should consider concatenation of two tstrings first. Having this, you may decide to allow your tstring(const char *) constructor to deal with conversion for you. This way you will get concatenation with C-strings free.

Then you'll notice that tstring + char [] does not yield the same result as char [] + tstring. That is because first will call your converting constructor and second will not find any matching operator.

As having asymmetrical operator+ is counterintuitive, you should also provide non-member operator+(const char *, tstring const &) that will forward its arguments to its in-class sibling.

Adam Sosnowski
  • 1,126
  • 9
  • 7
  • again a matter of preference, but I'd just declare one `friend operator+(tstring, tstring)`, and with the implicit constructor everything will just work. – vsoftco Feb 15 '15 at 20:20