@src: http://www.java2s.com/Code/Cpp/Overload/Friendlyoperator.htm
make -k main && ./main g++ main.cpp -o main main.cpp: In function 'int main()': main.cpp:158: warning: deprecated conversion from string constant to 'char*' main.cpp:170: error: ambiguous overload for 'operator+' in 'c1 + s2' main.cpp:139: note: candidates are: n::String operator+(const n::String&, const n::String&) main.cpp:35: note: n::String n::operator+(const n::String&, const n::String&)
#include <cstdio> #define LOGf(f,...) printf( f "\n", __VA_ARGS__ ) //std #define LOG() LOGf("%s:%d: %s ### ", __FILE__, __LINE__ , __PRETTY_FUNCTION__) #include <iostream> #include <string.h> using namespace std; #if 1 # define SUPPORT_NAMESPACE 1 # define SUPPORT_FRIEND 1 # define SUPPORT_INLINE 0 # define SUPPORT_OP 1 #elif 0 # define SUPPORT_NAMESPACE 1 # define SUPPORT_FRIEND 1 # define SUPPORT_INLINE 0 # define SUPPORT_OP 1 #elif 0 # define SUPPORT_NAMESPACE 1 # define SUPPORT_FRIEND 1 # define SUPPORT_INLINE 1 # define SUPPORT_OP 1 #elif 0 // bug # define SUPPORT_NAMESPACE 1 // uncomment to for bug # define SUPPORT_FRIEND // main.cpp:181: error: ambiguous overload for 'operator+' in 's1 + s2' // main.cpp:148: note: candidates are: n::String operator+(const n::String&, const n::String&) // main.cpp:44: note: n::String n::operator+(const n::String&, const n::String&) #elif 0 //working # define SUPPORT_NAMESPACE # define SUPPORT_OP #elif 1 // working # define SUPPORT_FRIEND # define SUPPORT_OP #endif #if SUPPORT_NAMESPACE namespace n { #endif class String; String operator+(const String&, const String&); class String{ public: String(); String(const char *const); String(const String &); ~String(); char & operator[](int offset); char operator[](int offset) const; #ifdef SUPPORT_OP String operator+(const String&) /*const*/; #endif #if (SUPPORT_FRIEND) #if ! SUPPORT_INLINE friend String operator+(const String&, const String&); #else friend String operator+(const String & lhs, const String& rhs) { LOG(); int totalLen = lhs.GetLen() + rhs.GetLen(); n::String temp(totalLen); int i, j; for (i = 0; i<lhs.GetLen(); i++) temp[i] = lhs[i]; for (j = 0, i = lhs.GetLen(); j<rhs.GetLen(); j++, i++) temp[i] = rhs[j]; temp[totalLen]='\0'; return temp; } #endif #endif void operator+=(const String&); String & operator= (const String &); int GetLen()const { return itsLen; } const char * GetString() const { return itsString; } String (int); char * itsString; unsigned short itsLen; }; #if SUPPORT_NAMESPACE } #endif #if ( SUPPORT_FRIEND ) #if ( !SUPPORT_INLINE ) n::String n::operator+(const n::String& lhs, const n::String& rhs) { LOG(); int totalLen = lhs.GetLen() + rhs.GetLen(); n::String temp(totalLen); int i, j; for (i = 0; i<lhs.GetLen(); i++) temp[i] = lhs[i]; for (j = 0, i = lhs.GetLen(); j<rhs.GetLen(); j++, i++) temp[i] = rhs[j]; temp[totalLen]='\0'; return temp; } #endif #endif #if SUPPORT_NAMESPACE using namespace n; #endif String::String() { itsString = new char[1]; itsString[0] = '\0'; itsLen=0; } String::String(int len) { itsString = new char[len+1]; for (int i = 0; i<=len; i++) itsString[i] = '\0'; itsLen=len; } String::String(const char * const cString) { itsLen = strlen(cString); itsString = new char[itsLen+1]; for (int i = 0; i<itsLen; i++) itsString[i] = cString[i]; itsString[itsLen]='\0'; } String::String (const String & rhs) { itsLen=rhs.GetLen(); itsString = new char[itsLen+1]; for (int i = 0; i<itsLen;i++) itsString[i] = rhs[i]; itsString[itsLen] = '\0'; } String::~String () { delete [] itsString; itsLen = 0; } String& String::operator=(const String & rhs) { if (this == &rhs) return *this; delete [] itsString; itsLen=rhs.GetLen(); itsString = new char[itsLen+1]; for (int i = 0; i<itsLen;i++) itsString[i] = rhs[i]; itsString[itsLen] = '\0'; return *this; } char & String::operator[](int offset) { if (offset > itsLen) return itsString[itsLen-1]; else return itsString[offset]; } char String::operator[](int offset) const { if (offset > itsLen) return itsString[itsLen-1]; else return itsString[offset]; } #ifdef SUPPORT_OP String String::operator+(const String& rhs) /*const*/ { LOG(); int totalLen = itsLen + rhs.GetLen(); String temp(totalLen); int i, j; for (i = 0; i<itsLen; i++) temp[i] = itsString[i]; for (j = 0, i = itsLen; j<rhs.GetLen(); j++, i++) temp[i] = rhs[j]; temp[totalLen]='\0'; return temp; } #endif int main() { #if SUPPORT_FRIEND String const s1("String One "); String const s2("String Two "); #else String s1("String One "); String s2("String Two "); #endif char *c1 = "C-String One "; String s3; String s4; String s5; cout << "s1: " << s1.GetString() << endl; cout << "s2: " << s2.GetString() << endl; cout << "c1: " << c1 << endl; //s3 = ::operator+( s1 , s2 ); s3 = s1 + s2; #if 1 cout << "s3: " << s3.GetString() << endl; s4 = s1 + c1; cout << "s4: " << s4.GetString() << endl; #endif #if SUPPORT_FRIEND s5 = c1 + s2; cout << "s5: " << s5.GetString() << endl; #endif return 0; }