본문 바로가기

C++

[C++] 포인터 - 연산자 오버로딩(overloading)

이번에는 연산자 오버로딩에 대해서 아래의 샘플코드를 통해서 알아보자.

 

#include <iostream>

class Complex
{
private:
  double real, img;
  double get_number(const char *str, int from, int to) const;
  // 함수에 const 를 사용하면 해당 함수내부에서는 멤버 변수값을 변경못함.

public:
  Complex(double real, double img) : real(real), img(img) {}
  Complex(const Complex &c) { real = c.real, img = c.img; }
  Complex(const char *str);

// a@b 는 a.operator@(b) 또는 operator@(a,b) 로 해석이 가능하다.
// 첫번째만 정의한 경우, a.operator@(b)만 정의할 경우는 const 키워드 유무와 상관없이 정상
// 둘다 정의한 경우, 2개의 함수중 어떤것을 콜해야하는지 몰라서 오류발생
// a+"1+i" 는 둘다 연산가능, "i+1"+a 는 두번째로만 연산가능

// operator+에서 const 키워드가 없어야 오류가 없음(operator@(a,b) 구현했기때문임).
  Complex operator+(const Complex &c);
  Complex operator-(const Complex &c) const;
  Complex operator*(const Complex &c) const;
  Complex operator/(const Complex &c) const;

  // Complex operator+(const char *str) const;
  // Complex operator-(const char *str) const;
  // Complex operator*(const char *str) const;
  // Complex operator/(const char *str) const;

  Complex &operator=(const Complex &c);
  void println() { std::cout << "( " << real << " , " << img << " ) " << std::endl; }

  Complex &operator+=(const Complex &c);
  Complex &operator-=(const Complex &c);
  Complex &operator*=(const Complex &c);
  Complex &operator/=(const Complex &c);
};

Complex::Complex(const char *str)
{
  // 입력 받은 문자열을 분석하여 real 부분과 img 부분을 찾아야 한다.
  // 문자열의 꼴은 다음과 같습니다 "[부호](실수부)(부호)i(허수부)"
  // 이 때 맨 앞의 부호는 생략 가능합니다. (생략시 + 라 가정)

  int begin = 0, end = strlen(str);
  img = 0.0;
  real = 0.0;

  // 먼저 가장 기준이 되는 'i' 의 위치를 찾는다.
  int pos_i = -1;
  for (int i = 0; i != end; i++)
  {
    if (str[i] == 'i')
    {
      pos_i = i;
      break;
    }
  }

  // 만일 'i' 가 없다면 이 수는 실수 뿐이다.
  if (pos_i == -1)
  {
    real = get_number(str, begin, end - 1);
    return;
  }

  // 만일 'i' 가 있다면,  실수부와 허수부를 나누어서 처리하면 된다.
  real = get_number(str, begin, pos_i - 1);
  img = get_number(str, pos_i + 1, end - 1);
  // printf("str[%s], begin[%d], pos_i[%d], end[%d]\n", str, begin, pos_i, end);

  if (pos_i == end - 1)
    img = 1;

  if (pos_i >= 1 && str[pos_i - 1] == '-')
    img *= -1.0;
}

Complex Complex::operator+(const Complex &c)
{
  Complex temp(real + c.real, img + c.img);
  return temp;
}
Complex Complex::operator-(const Complex &c) const
{
  Complex temp(real - c.real, img - c.img);
  return temp;
}
Complex Complex::operator*(const Complex &c) const
{
  Complex temp(real * c.real - img * c.img, real * c.img + img * c.real);
  return temp;
}
Complex Complex::operator/(const Complex &c) const
{
  Complex temp(
      (real * c.real + img * c.img) / (c.real * c.real + c.img * c.img),
      (img * c.real - real * c.img) / (c.real * c.real + c.img * c.img));
  return temp;
}

Complex &Complex::operator=(const Complex &c)
{
  // TODO: insert return statement here
  real = c.real;
  img = c.img;
  return *this;
}

Complex &Complex::operator+=(const Complex &c)
{
  *this = *this + c;
  return *this;
}

Complex &Complex::operator-=(const Complex &c)
{
  *this = *this - c;
  return *this;
}

Complex &Complex::operator*=(const Complex &c)
{
  *this = *this * c;
  return *this;
}

Complex &Complex::operator/=(const Complex &c)
{
  *this = *this / c;
  return *this;
}

// Complex Complex::operator+(const char *str) const
// {
//   Complex temp(str);
//   return (*this) + temp;
// }

// Complex Complex::operator-(const char *str) const
// {
//   Complex temp(str);
//   return (*this) - temp;
// }
// Complex Complex::operator*(const char *str) const
// {
//   Complex temp(str);
//   return (*this) * temp;
// }
// Complex Complex::operator/(const char *str) const
// {
//   Complex temp(str);
//   return (*this) / temp;
// }

double Complex::get_number(const char *str, int from, int to) const
{
  bool minus = false;
  if (from > to)
    return 0;

  if (str[from] == '-')
    minus = true;
  if (str[from] == '-' || str[from] == '+')
    from++;

  double num = 0.0;
  double decimal = 1.0;

  bool integer_part = true;
  for (int i = from; i <= to; i++)
  {
    if (isdigit(str[i]) && integer_part)
    {
      num *= 10.0;
      num += (str[i] - '0');
    }
    else if (str[i] == '.')
      integer_part = false;
    else if (isdigit(str[i]) && !integer_part)
    {
      decimal /= 10.0;
      num += ((str[i] - '0') * decimal);
    }
    else
      break; // 그 이외의 이상한 문자들이 올 경우
  }

  if (minus)
    num *= -1.0;

  return num;
}

Complex operator+(const Complex &a, const Complex &b)
{
  Complex temp(a);
  return temp.operator+(b);
}

int main()
{
  // Complex a(1.0, 2.0);
  // Complex b(3.0, -2.0);
  // Complex c = a * b;     // (7,4)
  // Complex d = b + c + b; // ( 13 , 0 ), error ( 20 , 4 )
  // c.println();
  // d.println();

  // Complex a(1.0, 2.0);
  // Complex b(3.0, -2.0);
  // Complex c(0.0, 0.0);
  // c = a * b + a / b + a + b;
  // c.println();
  // b = a;
  // c.println();

  // Complex a(1.0, 2.0);
  // Complex b(3.0, -2.0);
  // a += b;
  // a.println();
  // b.println();

  // Complex a(0, 0);
  // // a = a + "-1.1 + i3.923";
  // a = a + "-i";
  // a.println();

  Complex a(0, 0);
  a = a + "-1.1 + i3.923";
  a.println();
  a = a - "1.2 -i1.823";
  a.println();
  a = a * "2.3+i22";
  a.println();
  a = a / "-12+i55";
  a.println();

  a = "-1.0 + i3.0" + a;
  a.println();
  a = "-1.0 + i3.0" + a;
  a.println();
}