@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;
}


i160.photobucket.com_albums_t193_miggetymary_morticia-addams.jpg

friend.txt · Last modified: 2022/04/16 12:23 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki