본문 바로가기
OLD/[C++]개념정리

[개탱][C++][Operator Overloading][Operator][Overloading][복소수][complexNumber][1]

by 개탱 2018. 1. 2.
728x90

Operator Overloading

 ex ) X = "Kim" + "Lee" 를  하고

X를 출력해서  KimLee 가 출력되게 하고싶은데 기본 C에서는 이게 불가능하다.

이때 C++에서 이를 가능하게 해주게 하기위해서 Operator Overloading  이다.


[JAVA 에서는 사용 불가]


 ex)복소수를 다룰 때 

 a = 3.1 + 5.4i

 b = 1.6 + 1.3i

 c = a + b; 

이렇게 하나의 변수에 실수와 허수를 동시에 담아야 하니까 Class(구조체↑)를 사용하면 좋다.

이를 예시로 코드를 짜보겠다.


그저 완성된 마지막 코드를 원한다면

제일 밑을 보세요!




먼저 복소수의 실수와 허수를 저장하기 위해


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ComplexNumber {
private :
    double m_x; // 실수부분 저장
    double m_y; // 허수부분 저장
  
public :
    ComplexNumber();
};
 
ComplexNumber::ComplexNumber()
{
    m_x = 0// 처음에는 기본적으로 사용하지 않는경우에는
    m_y = 0// 0이라는 값이 입력이 되어있는게 좋음
}
 
cs



이렇게 클래스를 하나 만들어서  실수와 허수를 저장할 변수를 지정해준다.


 그 뒤 



1
2
3
4
5
int main()
{
    ComplexNumber a;
    ComplexNumber b;
}
cs



 이렇게 함으로서 a와 b라는 복소수 2개를 만들어 줬다.



1
2
3
4
5
6
7
8
9
10
11
12
class ComplexNumber {
private :
    double m_x; // 실수부분 저장
    double m_y; // 허수부분 저장
 
public :
    ComplexNumber();
    void print() {
        cout << m_x << " + " << m_y << "i" << endl;
    }
};
 
cs



그 뒤 복소수의 현재값을 출력해주는 함수를 만들어서 출력을 해보자.


1
2
3
4
5
6
7
int main()
{
    ComplexNumber a;
    ComplexNumber b;
    a.print();
    b.print();
}
cs

위와 같은 결과가 나오게된다. 처음 클래스 생성자에 m_x 와 m_y 에 0의 값을 넣을수 있게 해주었기 때문에

0+ 0i 라는 값이 2번 출력이 되게 된다. 여기서 값을 이제 입력시켜줄때

처음 생성할때부터 값이 입력이 되게해주면 얼마나 좋을까 해서


1
2
3
4
5
ComplexNumber(double x, double y) {
        m_x = x;
        m_y = y;
    }
 
cs


생성자를 하나 오버로딩 해주도록 한다.

(오버로딩 혹시나 모르면)

http://gaetaeng.tistory.com/28

[Function Overloading][operator overloading][함수 오버로딩]

 

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
32
33
34
35
36
37
#define _CRT_SECURE_NO_WARNINGS
 
#include <iostream>
 
using namespace std;
 
class ComplexNumber {
private :
    double m_x; // 실수부분 저장
    double m_y; // 허수부분 저장
  // 허수부분 저장
public :
    ComplexNumber();
    ComplexNumber(double x, double y) {
        m_x = x;
        m_y = y;
    }
    void print() {
        cout << m_x << " + " << m_y << "i" << endl;
    }
};
 
ComplexNumber::ComplexNumber()
{
    m_x = 0// 처음에는 기본적으로 사용하지 않는경우에는
    m_y = 0// 0이라는 값이 입력이 되어있는게 좋음
}
 
 
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    a.print();
    b.print();
}
 
cs



그렇게해서 나오는 결과가 위에 코드이다.


여기서 우리가 원하는 것은 복소수 + 복소수 (a + b)의 결과로 복소수가 하나 나와서 c에 저장이 되는 결과이다.

나는 여기서 a에다가 b를 더하는 것을 c에 넣는다고 하여

1
2
3
4
5
6
7
8
9
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    a.print();
    b.print();
 
    c = a.add(b);
}
cs


이런 식으로 사용을 하려한다. 그래서 

반환형이  ComplexNumber 이며 함수이름 add 매개변수 b를 받을 ComplexNumber 형 타입의 매개변수 x 1개라는 함수를 만든다.


1
2
3
4
5
6
7
8
9
10
11
12
ComplexNumber add(ComplexNumber x) {
        ComplexNumber tmp;        // 창고로 쓸 ComplexNumber 형 변수
        tmp.m_x = m_x + x.m_x;    // tmp라는 창고변수에 a의 m_x와 매개변수로 
                                //들어온 ComplexNumber 형의 m_x의 값을 더한것을 넣어준다
                                // 여기서 왜 m_x가 a의 것이냐면 
                                // 현재 m_x 앞에는 this. 가 숨어있으며 현재 this가 가리키는 곳은
                                // add를 불러온 위치인 a이다.
        tmp.m_y = m_y + x.m_y;
        return tmp;
 
    }
 
cs


그 결과코드로 아래와 같은 코드들이 생성이 된다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#define _CRT_SECURE_NO_WARNINGS
 
#include <iostream>
 
using namespace std;
 
class ComplexNumber {
private :
    double m_x; // 실수부분 저장
    double m_y; // 허수부분 저장
 
public :
    ComplexNumber();
    ComplexNumber(double x, double y) {
        m_x = x;
        m_y = y;
    }
    void print() {
        cout << m_x << " + " << m_y << "i" << endl;
    }
 
    ComplexNumber add(ComplexNumber x) {
        ComplexNumber tmp;        // 창고로 쓸 ComplexNumber 형 변수
        tmp.m_x = m_x + x.m_x;    // tmp라는 창고변수에 a의 m_x와 매개변수로 
                                //들어온 ComplexNumber 형의 m_x의 값을 더한것을 넣어준다
                                // 여기서 왜 m_x가 a의 것이냐면 
                                // 현재 m_x 앞에는 this. 가 숨어있으며 현재 this가 가리키는 곳은
                                // add를 불러온 위치인 a이다.
        tmp.m_y = m_y + x.m_y;
        return tmp;
 
    }
 
};
 
ComplexNumber::ComplexNumber()
{
    m_x = 0// 처음에는 기본적으로 사용하지 않는경우에는
    m_y = 0// 0이라는 값이 입력이 되어있는게 좋음
}
 
 
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    ComplexNumber c;
    a.print();
    b.print();
 
    c = a.add(b);
    c.print();
}
 
cs



하지만 이런식으로 사용을 하게되면 문제가 많이 생긴다고한다. 

또한 a와 b를 더하는건데 왜 tmp라는 변수와 x라는 입력받을 변수를 받을 변수를

또 만들어서 더해야하나? 라는 생각이 들수도있다.

평소 int형 a 와 b를 더하고 할때에는 그냥 a+b를 하면 되는데

굳이 tmp 를 만들 필요가 없다. 그래서 생각이 난게 &(Address Type)


1
2
3
4
5
6
7
8
9
10
11
12
ComplexNumber add(ComplexNumber &x) {Address Type 을 사용해줌으로서 별명으로 처리를 해준다.
        ComplexNumber tmp;        // 창고로 쓸 ComplexNumber 형 변수
        tmp.m_x = m_x + x.m_x;    // tmp라는 창고변수에 a의 m_x와 매개변수로 
                                //들어온 ComplexNumber 형의 m_x의 값을 더한것을 넣어준다
                                // 여기서 왜 m_x가 a의 것이냐면 
                                // 현재 m_x 앞에는 this. 가 숨어있으며 현재 this가 가리키는 곳은
                                // add를 불러온 위치인 a이다.
        tmp.m_y = m_y + x.m_y;
        return tmp;
 
    }
 
cs

아까만든 add에서 Address Type을 사용하게 함으로서 x라는 이름은 사용을 하지만 b의 실제값 자체를 가져오게 되서

직접적인 b를 사용하게 된다.

Address Type 에 대해서는 나중에 한번 적어두겠습니다!



자 위처럼 하게 되어도.. ComplexNumber 타입의 tmp를 생성해서 만들게 되는데 이를 방지하기 위해서 

 

1
2
3
4
ComplexNumber add(ComplexNumber &x) {
        return ComplexNumber(m_x + x.m_x, m_y + x.m_y);
    }
 
cs

이렇게 사용을 해줌으로서

ComplexNumber 형을 생성자로 만들어진후에 바로 return 을 함으로서 코드줄도 줄이고 쓸데없는 변수사용이 줄어들었다.

그런데 처음에 우리가 원하던것은 

a.add(b) 이게 아닌

c= a+b 이다.

그래서 우리는

아래의 코드에서

1
2
3
4
5
6
7
8
9
10
11
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    ComplexNumber c;
    a.print();
    b.print();
 
    c = a.add(b);
    c.print();
}
cs



1
2
3
4
5
6
7
8
9
10
11
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    ComplexNumber c;
    a.print();
    b.print();
 
    c = a.operator+(b);
    c.print();
}
cs



add의 이름을 operator+ 로 바꾸어보자

이렇게 변경후


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ComplexNumber {
private :
    double m_x; // 실수부분 저장
    double m_y; // 허수부분 저장
 
public :
    ComplexNumber();
    ComplexNumber(double x, double y) {
        m_x = x;
        m_y = y;
    }
    void print() {
        cout << m_x << " + " << m_y << "i" << endl;
    }
 
    ComplexNumber operator+(ComplexNumber &x) {
        return ComplexNumber(m_x + x.m_x, m_y + x.m_y);
    }
 
};
 
cs



클래스 내부에서도 수정을 해보자.


그뒤 ! main 에서 operator+ 를 그냥 + 로 바꾸면


1
2
3
4
5
6
7
8
9
10
11
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    ComplexNumber c;
    a.print();
    b.print();
 
    c =  a + b;
    c.print();
}
cs





​이렇게 정상적인 결과가 나오게 된다!

언븰리버블!


이것을 응용하여 ! 음수도 만들어주면

1
2
3
4
ComplexNumber operator-(ComplexNumber &x) {
        return ComplexNumber(m_x + x.m_x, m_y + x.m_y);
    }
 
cs

이렇게 만들어 주며



실수값과 허수값을 가져오기 위해서는

1
2
3
4
5
6
double real() {
        return m_x;
    }
    double imaginary() {
        return m_y;
    }
cs


​이렇게 구현하면 된다.


또한 복소수의 제곱근을 구하기 위해서는 


1
2
3
4
double magnitude() {
        return sqrt(m_x*m_x + m_y*m_y);
    }
 
cs



​또한 곱셈을 위해서는 


1
2
3
4
5
6
7
8
ComplexNumber operator*(ComplexNumber &x) {
        //곱셈은 실수*실수-허수*허수 ( i의 제곱은 -1이다 )
        //this.실수 * 실수 - this.허수 * 허수  //실수 부분
        //+ this.실수 * 허수i + 실수 * this.허수i //허수부분
        double realPart = m_x * x.m_x - m_y*m_y ;
        double imaginaryPart = m_x*x.m_x + m_y*x.m_y;
        return ComplexNumber(realPart ,imaginaryPart);
    }
cs


이렇게 만들어 주면 된다.


마지막 최종코드 


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#define _CRT_SECURE_NO_WARNINGS
 
#include <iostream>
#include <math.h>
using namespace std;
 
class ComplexNumber {
private ://생략하면 기본적으로 default 가 private 임.
    double m_x; // 실수부분 저장
    double m_y; // 허수부분 저장
 
public :
    ComplexNumber();
    ComplexNumber(double x, double y) {
        m_x = x;
        m_y = y;
    }
    void print() {
        //허수부분의 값이 -인경우 바꾸어줘야 하지만
        // 그 정도는 할수있을거라 믿습니다! ㅎㅎㅎㅎ
        cout << m_x << " + " << m_y << "i" << endl;
    }
    double real() {
        return m_x;
    }
    double imaginary() {
        return m_y;
    }
 
    double magnitude() {
        return sqrt(m_x*m_x + m_y*m_y);
    }
 
    ComplexNumber operator+(ComplexNumber &x) {
        return ComplexNumber(m_x + x.m_x, m_y + x.m_y);
    }
    ComplexNumber operator-(ComplexNumber &x) {
        return ComplexNumber(m_x + x.m_x, m_y + x.m_y);
    }
    ComplexNumber operator*(ComplexNumber &x) {
        //곱셈은 실수*실수-허수*허수 ( i의 제곱은 -1이다 )
        //this.실수 * 실수 - this.허수 * 허수  //실수 부분
        //+ this.실수 * 허수i + 실수 * this.허수i //허수부분
        return ComplexNumber(m_x * x.m_x - m_y*m_y ,m_x*x.m_x + m_y*x.m_y);
    }
    //ComplexNumber operator*(ComplexNumber &x) {
    //    double realPart = m_x * x.m_x - m_y*m_y ;
    //    double imaginaryPart = m_x*x.m_x + m_y*x.m_y;
    //    return ComplexNumber(realPart ,imaginaryPart);
    //}
 
};
 
ComplexNumber::ComplexNumber()
{
    m_x = 0// 처음에는 기본적으로 사용하지 않는경우에는
    m_y = 0// 0이라는 값이 입력이 되어있는게 좋음
}
 
 
int main()
{
    ComplexNumber a(3.1,5.4);
    ComplexNumber b(1.6,1.3);
    ComplexNumber c;
    a.print();
    b.print();
 
 
    //양수 계산
    c =  a + b;
    c.print();
 
 
    //음수 계산
    c =  a - b;
    c.print();
 
    //실수부분 추출
    double r = a.real();
    cout << "실수 출력 :: " << r << endl;
    double i = a.imaginary();
    cout << "허수 출력 :: " << i << endl;
 
    ComplexNumber e;
 
    e = a * b;
    e.print();
 
}
 
cs


댓글