카테고리 없음

코딩 연습 #1 클래스, 함수 오버로딩 230502

마쿠어 2023. 5. 2. 00:32
#include<iostream>
using namespace std;

class Complex
{
        public:
                Complex(float r=0.0, float i=0.0) :re(r), im(i) {}
                Complex operator+(const Complex &coma, const Complex &comb)
                        {
                                return Complex(coma.re+comb.re , coma.im+comb.im);
                        }
//              Complex operator-(const Complex &coma, const Complex &comb)

                void Print() { cout << re << " + " << im << " i \n "; }

        private:
                float re, im;

};

int main()
{
        Complex com1(1.0, 2.0), com2(3.0, 4.0);
        Complex com3, com4, com5, com6;

        com1.Print();
        com2.Print();

        com3 = com1 + com2;
        com3.Print();
}

우선 연습 삼아서 + 연산자를 오버로딩 하는 방식으로 만들어 보았으나 다음과 같은 오류가 있었다.

 

1. operator 선언 단계에서 2개의 인자를 받는 것이 틀렸다

 

operator의 경우 this 포인터를 사용하여 인자 자체에 접근하게 되므로, 2개의 인자가 아닌 하나의 인자를 전달해야 한다. 따라서 아래의 코드로 변경하여 +에 대한 정상적인 작동을 확인하였다.

#include<iostream>
using namespace std;

class Complex
{
        public:
                Complex(float r=0.0, float i=0.0) :re(r), im(i) {}
                Complex operator+(const Complex &com0)
                        {
                                return Complex(com0.re + re , com0.im + im);
                        }
//              Complex operator-(const Complex &coma, const Complex &comb)

                void Print() { cout << re << " + " << im << " i \n"; }

        private:
                float re, im;

};

int main()
{
        Complex com1(1.0, 2.0), com2(3.0, 4.0);
        Complex com3, com4, com5, com6;

        com1.Print();
        com2.Print();

        com3 = com1 + com2;
        com3.Print();
}

 

 이후 작업은 뺄셈, 곱셈, 나눗셈 operator를 추가하고, 출력에서도 음수의 경우 -2 + -2i 가 아닌 -2 - 2i 의 형태로 출력되도록 코드를 작성할 것이다. [ if, else 를 print 함수에 추가할 예정]

 

[1차 작업안]

#include<iostream>
using namespace std;

class Complex
{
        public:
                Complex(float r=0.0, float i=0.0) :re(r), im(i) {}
                Complex operator+(const Complex &com0)
                        {
                                return Complex(com0.re + re , com0.im + im);
                        }
                Complex operator-(const Complex &com0)
                        {
                                return Complex(com0.re - re , com0.im - im);
                        }
                Complex operator*(const Complex &com0)
                        {
                                return Complex(com0.re * re , com0.im * im);
                        }
                Complex operator/(const Complex &com0)
                        {
                                return Complex(com0.re / re , com0.im / im);
                        }
                void Print()
                        {
                                if (im >= 0)
                                        cout << re << " + " << im << " i \n";
                                else
                                        cout << re << im << " i \n";
                        }

        private:
                float re, im;
};

int main()
{
        Complex com1(1.0, 2.0), com2(3.0, 4.0);
        Complex com3, com4, com5, com6;

        com1.Print();
        com2.Print();

        com3 = com1 + com2;
        com3.Print();

        com4 = com1 - com2;
        com4.Print();

        com5 = com1*com2;
        com5.Print();

        com6 = com1/com2;
        com6.Print();
}

이렇게 작업한 결과 com4,5,6에서 결과가 정상적으로 출력되지 않는다.

-2 -2i 가 출력돼야 하지만, 2 + 2i가 출력

곱에서도 3 , 8 , 나눗셈에서는 3, 2가 출력된다.

 

하지만 문제에서 주어진 값과 다르게 결과가 산출된다

*우선 기본적으로 곱셈과 나눗셈에 대한 이해가 잘못되었다. 문제 상단부에 적힌 연산식으로 해야했음

하지만 이 외에도 뺄셈과 나눗셈에서 내가 생각한 것과 다른 결과가 나왔으므로 이를 확인하는 단계

 

문제점 1. 뺄셈, 나눗셈 문제 발생 이유 [operator에 대한 이해 매우 중요!!]

 

operator 의 기본적인 구성은 "호출 객체"와 "전달 객체"이다. operator를 배우기 전 우리는 함수 호출에서 add.p1(p2) 로 호출하였다. 이 경우 호출 객체(host)가 p1이고, 전달 객체(손님)이 p2이다. 동일하게 operator에서도 operator+(Complex &com0)에서 com0는 '전달 객체'이다. 즉, 위에서 p2에 해당한다. 이를 p1 + p2로 표현한다면, p1은 호출 객체이고 p2는 전달 객체이다.

덧셈의 경우 문제가 없었지만, 뺄셈, 나눗셈의 경우 연산의 순서가 중요하므로 문제가 발생한 것이다.

 

따라서 본래 내가 생각하는 방식으로 작동하기 위해서는 우선 각 operator 내 함수에서 com0의 위치가 뒤로 가야 한다. 현재 코드에서는 호출 객체와 전달 객체의 위치가 뒤바뀌어 있다.

 

<문제에서 제공된 연산 순서대로 수정한 코드>

class Complex
{
        public:
                Complex(float r=0.0, float i=0.0) :re(r), im(i) {}
                Complex operator+(const Complex &com0)
                        {
                                return Complex(com0.re + re , com0.im + im);
                        }
                Complex operator-(const Complex &com0)
                        {
                                return Complex(re - com0.re , im - com0.im);
                        }
                Complex operator*(const Complex &com0)
                        {
                                return Complex((re * com0.re)-(im * com0.im), (im * com0.re)+(re * com0.im) );
                        }
                Complex operator/(const Complex &com0)
                        {
                                return Complex(((re * com0.re) + (im * com0.im)) / ((com0.re*com0.re)+(com0.im*com0.im))), ((im*com0.re) - (re*com0.im) / ((com0.re*com0.re)+(com0.im*com0.im)));
                        }

나눗셈을 제외하고는 모두 정상 출력되었다. 나눗셈의 경우 괄호 배정에 있어서 문제가 있어서 수정한 것은 다음과 같다

 

#include<iostream>
using namespace std;

class Complex
{
        public:
                Complex(float r=0.0, float i=0.0) :re(r), im(i) {}
                Complex operator+(const Complex &com0)
                        {
                                return Complex(com0.re + re , com0.im + im);
                        }
                Complex operator-(const Complex &com0)
                        {
                                return Complex(re - com0.re , im - com0.im);
                        }
                Complex operator*(const Complex &com0)
                        {
                                return Complex((re * com0.re)-(im * com0.im), (im * com0.re)+(re * com0.im) );
                        }
                Complex operator/(const Complex &com0)
                        {
                                return Complex((((re * com0.re) + (im * com0.im)) / ((com0.re*com0.re)+(com0.im*com0.im))), (((im*com0.re) - (re*com0.im)) / ((com0.re*com0.re)+(com0.im*com0.im))));
                        }
                void Print()
                        {
                                if (im >= 0)
                                        cout << re << " + " << im << "i \n";
                                else
                                        cout << re << " "  << im << "i \n";
                        }

                                private:
                                        float re, im;
};

연산 operator 부분을 수정하는 경우 최종적으로 다음과 같은 코드를 갖게 된다.

 

 

오늘 수정한 주요 사항

1. operator의 경우 '호출 객체'와 '전달 객체'로 나뉜다는 사실 - 특히나 뒤에 오는 것이 전달 객체임을 반드시 인지해야 한다.

2. this 문을 사용하기에, 2개의 전달인자가 사용되지 않는 다는 사실

3. 객체 마지막에는 반드시 세미클론을 달아줘야 한다는 사실

 

 

크게 위의 3가지 내용이 함수 오버로딩에 있어서 중요한 요소였다.