| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- 후위
- 템플릿 함수화
- Tree
- Windows
- 문자열
- array
- Python
- 숫자
- #선물 #비트코인#알트코인#매매#코인#마진
- 자료구조
- 오버로딩
- 트리
- 순회
- 전위
- 바이낸스
- 연결 리스트
- linked list
- Basic
- 기초
- Data Structure
- 알고리즘
- 선물
- template
- C++
- BST
- 이진 탐색 트리
- trading view
- 비트코인
- mutable
- SCM
- Today
- Total
Project Hub
7. 이항 연산자 오버로딩 본문
이전 글
2022.12.21 - [C++/c++ basic] - 6. Wrapper 클래스 - 타입변환 연산자
6. Wrapper 클래스 - 타입변환 연산자
이전 글 & 참고 글 2022.12.21 - [분류 전체보기] - 5. 연산자 오버로딩, friend 키워드 5. 연산자 오버로딩, friend 키워드 이전 글 2022.12.21 - [C++/c++ basic] - 4. implicit, explicit, mutable 키워드 4. implicit, explicit, m
projecthub.tistory.com
참고 글
2022.12.21 - [C++/c++ basic] - 5. 연산자 오버로딩, friend 키워드
5. 연산자 오버로딩, friend 키워드
이전 글 2022.12.21 - [C++/c++ basic] - 4. implicit, explicit, mutable 키워드 4. implicit, explicit, mutable 키워드 이전 글 2022.12.21 - [C++/c++ basic] - 3. copy consturctor 3. copy consturctor 이전 글 2022.12.21 - [C++/c++ basic] - 2. refer
projecthub.tistory.com
이항 연산자
우선, 아래와 같은 코드가 있다고 생각해보자.
#pragma once
#include <iostream>
class CComplex
{
public:
CComplex(double dReal, double dImg) : m_dReal(dReal), m_dImg(dImg) {};
CComplex(const char* pszString);
~CComplex();
// a = b + c + b 일 경우, &로 반환하면 첫번째 b + c를 수행하면, b의 값이 변경된다.
// 따라서 Complex& 형태가 아니라 Complex 형태로 반환을 하여 값을 리턴하도록 한다.
CComplex operator+(const CComplex& Complex) const;
CComplex operator-(const CComplex& Complex) const;
CComplex operator*(const CComplex& Complex) const;
CComplex operator/(const CComplex& Complex) const;
CComplex& operator=(const CComplex& Complex);
double GetNumber(const char* pszString, int iStart, int iEnd) const;
void println() { std::cout << "( " << m_dReal << ", " << m_dImg << " )" << std::endl; }
private:
double m_dReal;
double m_dImg;
};
CComplex::CComplex(const char* pszString)
{
int iIpos = -1;
m_dReal = 0.0;
m_dImg = 0.0;
for (int i = 0; i < strlen(pszString); i++)
{
if ('i' == pszString[i])
{
iIpos = i;
break;
}
}
if (-1 == iIpos)
{
m_dReal = GetNumber(pszString, 0, strlen(pszString) - 1);
}
else
{
m_dReal = GetNumber(pszString, 0, iIpos - 1);
m_dImg = GetNumber(pszString, iIpos + 1, strlen(pszString) - 1);
}
if (-1 != iIpos && '-' == pszString[iIpos - 1])
m_dImg += -1.0;
}
CComplex CComplex::operator+(const CComplex& Complex) const
{
CComplex temp(m_dReal + Complex.m_dReal, m_dImg + Complex.m_dImg);
return temp;
}
CComplex CComplex::operator-(const CComplex& Complex) const
{
CComplex temp(m_dReal - Complex.m_dReal, m_dImg - Complex.m_dImg);
return temp;
}
CComplex CComplex::operator*(const CComplex& Complex) const
{
CComplex temp((m_dReal * Complex.m_dReal) - (m_dImg * Complex.m_dImg),
(m_dReal * Complex.m_dImg) - (m_dImg * Complex.m_dReal));
return temp;
}
CComplex CComplex::operator/(const CComplex& Complex) const
{
CComplex temp((m_dReal * Complex.m_dReal) + (m_dImg * Complex.m_dImg) / (Complex.m_dReal * Complex.m_dReal) + (Complex.m_dImg * Complex.m_dImg),
(m_dImg * Complex.m_dReal) - (m_dReal * Complex.m_dImg) / (Complex.m_dReal * Complex.m_dReal) + (Complex.m_dImg * Complex.m_dImg));
return temp;
}
CComplex& CComplex::operator=(const CComplex& Complex)
{
m_dReal = Complex.m_dReal;
m_dImg = Complex.m_dImg;
return *this;
}
double CComplex::GetNumber(const char* pszString, int iStart, int iEnd) const
{
bool bIsMinus = false;
int iDotPos = -1;
double dNum = 0.0;
double dDecimal = 1.0;
if ('-' == pszString[iStart])
{
bIsMinus = true;
iStart++;
}
for (int i = iStart; i <= iEnd; i++)
{
if ('.' == pszString[i])
{
iDotPos = i;
break;
}
}
for (int i = iStart; i < iDotPos; i++)
{
if (isdigit(pszString[i]))
dNum += pszString[i] - '0';
}
for (int i = iDotPos + 1; i <= iEnd; i++)
{
if (isdigit(pszString[i]))
{
dDecimal /= 10.0;
dNum += (pszString[i] - '0') * dDecimal;
}
}
if (bIsMinus) dNum *= -1.0;
return dNum;
}
int main()
{
CComplex a(1.0, 1.0);
a = a + "-1.0 + i3.923";
a = "-1.0 + i3.923" + a;
return 0;
}
main 함수에 보면,
a = a + "-1.0 + i3.923";
a = "-1.0 + i3.923" + a;
이렇게 두 가지가 정의되어 있다. 보면, 같은 결과를 반환하는 것 같지만, 그렇지 않다.
아래의 경우에는 컴파일 되지 않는다.
이유는 다음과 같다.
먼저 a = a + "-1.0 + i3.923"; 의 경우,
1. a.operator+("-1.0 + i3.923") 으로 처리됨 (operator+(const char* pszString)가 없어도, implicit 로 인해 const char* 에서 CComplex 를 생성할 수 있는 생성자를 찾게되기 때문)
2. a.operator+(CComplex("3.0-i2.2324")); 으로 처리
와 같은 순서로 처리가 된다.
반면에 a = "-1.0 + i3.923" + a; 의 경우에는 이 같은 변형이 불가능하므로 컴파일 에러가 발생하게 된다.
이와 같은 문제를 해결하려면 어떻게 해야할까?
다행히도,
컴파일러는 이항연산자 (피연산자를 두 개를 취하는 연산자들. +, -, *, /, = 등등)를 다음과 같이 두 개의 방식으로 처리한다.
임의의 연산자 @ 에 대해서, a@b 는
a.operator@(b); -> operator@ 는 a 의 클래스의 멤버 함수로써 사용되는 것
operator@(a, b); -> operator@ 는 클래스 외부에 정의되어 있는 일반적인 함수를 의미. 해당 함수는 정의가 필요하다.
두번째 방식을 처리하기 위해서는 해당 함수를 만들고, CComplex 클래스의 friend로 지정하면 된다.
class CComplex
{
...
friend CComplex operator+(const CComplex& a, const CComplex& b);
};
CComplex operator+(const CComplex& a, const CComplex& b)
{
CComplex temp(a.m_dReal + b.m_dReal, a.m_dImg + b.m_dImg);
return temp;
}
위와 같은 함수를 추가하였다면, 컴파일 시 충돌 에러가 발생할 것이다.
이유는, 클래스 맴버 함수 중에 operator+가 존재하기 때문이다.
따라서 둘 중에 하나는 제거를 해주어야 한다.
기준은,
자기 자신을 리턴하는 이항 연산자일 경우(=, -=, = 등등) 멤버 함수로 설정을 하고,
아닌 애들은( +, -, *, / 등등)외부 함수로 정의한다.
#pragma once
#include <iostream>
class CComplex
{
public:
CComplex(double dReal, double dImg) : m_dReal(dReal), m_dImg(dImg) {};
CComplex(const char* pszString);
~CComplex();
CComplex& operator=(const CComplex& Complex);
double GetNumber(const char* pszString, int iStart, int iEnd) const;
void println() { std::cout << "( " << m_dReal << ", " << m_dImg << " )" << std::endl; }
friend CComplex operator+(const CComplex& ComplexA, const CComplex& ComplexB);
private:
double m_dReal;
double m_dImg;
};
CComplex operator+(const CComplex& ComplexA, const CComplex& ComplexB)
{
CComplex temp(ComplexA.m_dReal + ComplexB.m_dReal, ComplexA.m_dImg + ComplexB.m_dImg);
return temp;
}
CComplex::CComplex(const char* pszString)
{
int iIpos = -1;
m_dReal = 0.0;
m_dImg = 0.0;
for (int i = 0; i < strlen(pszString); i++)
{
if ('i' == pszString[i])
{
iIpos = i;
break;
}
}
if (-1 == iIpos)
{
m_dReal = GetNumber(pszString, 0, strlen(pszString) - 1);
}
else
{
m_dReal = GetNumber(pszString, 0, iIpos - 1);
m_dImg = GetNumber(pszString, iIpos + 1, strlen(pszString) - 1);
}
if (-1 != iIpos && '-' == pszString[iIpos - 1])
m_dImg += -1.0;
}
CComplex& CComplex::operator=(const CComplex& Complex)
{
m_dReal = Complex.m_dReal;
m_dImg = Complex.m_dImg;
return *this;
}
double CComplex::GetNumber(const char* pszString, int iStart, int iEnd) const
{
bool bIsMinus = false;
int iDotPos = -1;
double dNum = 0.0;
double dDecimal = 1.0;
if ('-' == pszString[iStart])
{
bIsMinus = true;
iStart++;
}
for (int i = iStart; i <= iEnd; i++)
{
if ('.' == pszString[i])
{
iDotPos = i;
break;
}
}
for (int i = iStart; i < iDotPos; i++)
{
if (isdigit(pszString[i]))
dNum += pszString[i] - '0';
}
for (int i = iDotPos + 1; i <= iEnd; i++)
{
if (isdigit(pszString[i]))
{
dDecimal /= 10.0;
dNum += (pszString[i] - '0') * dDecimal;
}
}
if (bIsMinus) dNum *= -1.0;
return dNum;
}
int main()
{
CComplex a(1.0, 1.0);
a = a + "-1.0 + i3.923";
a = "-1.0 + i3.923" + a;
return 0;
}
'C++ > c++ basic' 카테고리의 다른 글
| 9. 전위/후위 증감 연산자 오버로딩 & 첨자 연산자 오버로딩 (2) | 2022.12.21 |
|---|---|
| 8. 입출력 연산자 오버로딩 (2) | 2022.12.21 |
| 6. Wrapper 클래스 - 타입변환 연산자 (3) | 2022.12.21 |
| 5. 연산자 오버로딩, friend 키워드 (3) | 2022.12.21 |
| 4. implicit, explicit, mutable 키워드 (2) | 2022.12.21 |