I rather think I would go with something like:
String& operator+=(const String& s) const
const int length = _strLen + s._strLen ;
char* buffer = new char[length+1]; // room for terminator
std::copy(_strPtr, _strPtr + _strLen, buffer) ;
std::copy(s._strPtr, s._strPtr + s._strLen+1, buffer + _strLen) ;
delete  _strPtr ;
_strPtr = buffer ;
_strLen = length ;
Of course, that makes the assumption that _strLen
is the length of the string as opposed to being the number of chars allocated for the string and that all such strings are null terminated in the style of C strings.
The advantage of defining operator+=
first is that other addition operations may be defined in terms of that operator (and, because of that, don't need to be actual members of the class.) For instance, we might define operator+ as follows:
String operator+(String a, const String& b) // notice that the first parameter is taken by value
return a += b ;
The obvious place to start with a class is the constructors and assignment (and move) operations, not with operator overloads. Those should be correct before you move on.
As far as "friend declared member functions"... there is no such thing. Member functions have access to internals of the class - they don't need to be friends.