IT_Programming/C · C++

[C++] 연산자 오버로딩 정리와 예제...

JJun ™ 2009. 5. 16. 00:17

====================================================================================

 

[ 연산자 오버로딩 방법 ]

- 멤버 함수 : (해석) P1 + P2 = P1.operator + (P2)

                    (필수) = 연산자, [] 연산자,  ->연산자

- 전역함수 :  (해석) P1 + P2 = operator+(P1, P2)

                    (필수) 입출력(>>, <<) 연산자 오버로딩 (표준 C++ 라이브러리에 포함된 클래스인 경우),

                              이항 연산자에서 피연산자 교환문제 (좌측에 일반 변수가 오는 경우)

 

   나머지는 선택적으로 사용 가능하다. 단, 2가지 형태 모두 존재할 경우에는 멤버함수에 의한 연산자

   오버로딩이 우선권을 갖는다. ( but Visual Studio 6.0에서는 Error가 발생한다. )

 

====================================================================================

 

[ 연산자 오버로딩 시 고려사항 ]

- 기본 타입에 대한 의미를 변경할 수 없다.

- 연산자 오버로딩이 가능한 연산자를 알아 둬라.

   (불가능 : 멤버 접근 연산자(.) , 멤버 포인터 연산자(.*) , 범위 지정 연산자 (::) , 조건 연산자 (?:)

                 new, delete, sizeof, typeid, <static_cast><const_cast><dynamic_cast>

                 <reinterpret_cast> - 12 가지)

- 기존의 C++ 연산자가 아닌 연산자들에 대한 연산자 오버로딩은 불가능하다.

- 대입(=) 연산자와 주소(&) 연산자 오버로딩은 하지 않아도 모든 클래스 객체에 대해 사용할 수 있다.

- 연산자의 우선 순위를 바꿀 수 없다.

- 하나의 연산자에 대한 결합법칙을 바꿀 수 없다.

- 피연산자의 개수를 변경할 수 없다.

- 연산자 오버로딩을 위한 멤버함수는 디폴트 매개변수를 가질 수 없다. 

- 연산자 오버로딩이 가능한 연산자라 할지라도 기존의 연산자를 절대 흉내낼 수 없는 연산자도 있다.

   (&& 연산자, || 연산자, ,(쉼표) 연산자)

 

==================================================================================

 

/*

연산자 오버로딩을 하는 두가지 방법 (멤버함수, 전역함수)

예제 작성자 : creazier (블로그 주인장)

*/

 

#include<iostream>

 

using namespace std;

 

class CTime

{

    private :

        int Hour;

        int Minute;

        int Second;

 

    public :

        CTime(int h, int m, int s)

        {

            Hour = h;

            Minute = m;

            Second = s;

        }

  /* 멤버함수를 이용한 연산자 오버로딩   

        CTime operator+(const CTime &P0)

        {

            int tempHour=0;

            int tempMin=0;

            int tempSec=0;

            if((Second + P0.Second) > 60 || (Second + P0.Second) == 60)

            {

                tempMin = (Second + P0.Second)/60;

                tempSec = (-tempMin*60);

            }

 

            if((Minute + P0.Minute) > 60 || (Minute + P0.Minute) == 60)

            {

                tempHour = (Minute + P0.Minute)/60;

                tempMin = tempMin+(-tempHour*60);

            }

 

            return CTime(Hour + P0.Hour + tempHour, Minute + P0.Minute + tempMin,

                                        Second + P0.Second + tempSec);

        }

 */

        friend CTime operator+(const CTime &Po1, const CTime &Po2); // 전역 함수 선언

 

        void Print()

        {

            cout << Hour << "" << Minute << "" << Second << "" << endl;

        }

};

 

 

/* 전역함수를 이용한 연산자 오버로딩 */

CTime operator+(const CTime &Po1, const CTime &Po2)

{

        int h,m,s;

 

        s = Po1.Second+Po2.Second;

        m = Po1.Minute+Po2.Minute;

        h = Po1.Hour + Po2.Hour;

 

        m += s/60;

        s %= 60;

 

        h += m/60;

        m %= 60;

 

        h %=60;

 

        return CTime( h, m, s );

}

 

 

int main(void)

{

    CTime time1(4, 50, 40);

    CTime time2(3, 40, 30);

    CTime time3 = time1 + time2;

 

    time1.Print();

    time2.Print();

    time3.Print();

 

    return 0;

}

 

 

 

================================================================================

 

/*

연산자 오버로딩 종합

*/

#include <iostream>

#include <cstring>

 

using namespace std;

 

class CString

{

        private:

               char *str;

               int len;

 

        public:

               CString(char *s = "Unkonown");

               CString(const CString &CS);

               ~CString();

               CString operator+(const CString &CS);

               CString &operator=(const CString &CS);

               CString &operator+=(const CString &CS);

               bool operator==(const CString &CS);

 

// 귀찮아서 friend를 사용했지만 setter, getter를 사용하는 것이 좋다.

               friend ostream & operator<<(ostream &out, const CString CS);

               friend istream & operator>>(istream &in, CString &CS);

};

 

CString::CString(char *s) // 생성자

{

        len = strlen(s);

        str = new char[len+1];

        strcpy(str,s);

}

 

CString::CString(const CString &CS) // 복사 생성자 (깊은복사를 위해 필요)

{

        len = CS.len;

        str = new char[len+1];

        strcpy(str, CS.str); // 복사

}

 

CString::~CString() // 소멸자

{

        delete[] str;

}

 

CString CString::operator+(const CString &CS) // + 연산자 오버로딩

{

        char *temp_str = new char[len + CS.len + 2];

 

        strcpy(temp_str,str);

        temp_str[len] = ' ';

        strcpy(&(temp_str[len+1]),CS.str);

 

        return CString(temp_str);

}

 

CString &CString::operator=(const CString &CS) // = 연산자 오버로딩

{

        len = CS.len;

        delete[] str;

 

        str = new char[len+1];

        strcpy(str,CS.str);

 

        return *this;

}

 

CString &CString::operator+=(const CString &CS) // += 연산자 오버로딩

{

        (*this) = (*this) + CS;

        return (*this);

}

 

bool CString::operator==(const CString &CS) // == 연산자 오버로딩

{

        if( len == CS.len)

               return true;

        else

               return false;

}

 

ostream &operator<<(ostream &out, const CString CS) // 출력(<<) 연산자 오버로딩

{

        out  <<  CS.str;

        return out;

}

 

istream &operator>>(istream &in, CString &CS)  // 입력(>>) 연산자 오버로딩

{

        char *buffer = new char[50];

 

        in >> buffer;

 

        CS = CString(buffer);

 

        delete[] buffer;

        return in;

}

 

int main(void)

{

        CString str1 = "Good";

        CString str2 = "morning";

        CString str3;

 

        str3 = str1 + str2;

 

        cout << str1 << endl;

        cout << str2 << endl;

        cout << str3 << endl;

 

        str1 += str2;

 

        if( str1 == str3 )

        {

               cout << "equal!" << endl;

        }

 

 

        CString str4;

        cout << "문자열을입력하세요: ";

        cin >> str4;

        cout << "입력하신문자열은" << str4 << "입니다." << endl;

 

        return 0;

}

  

 

=================================================================================================

 

/* 배열 첨자 오버로딩 등을 이용해서 배열 인덱스 유효범위 체크하기 */

#include <iostream>

#include <cstdio>

#include <ctime>

 

using namespace std;

 

class CArray

{

             private:

                           int count;

                           int *ary;

 

             public:

                           CArray(int c);

                           ~CArray();

                           CArray(const CArray &CA);

                           CArray &operator=(const CArray &CA);

                           CArray operator+(const CArray &CA);

                           int &operator[](int index);

 

                           friend ostream & operator << (ostream &out, CArray &CA);

};

 

CArray::CArray(int c) // 생성자

{

             count = c;

             ary = new int[c];

 

             for(int i=0;i<c;i++)

                  ary[i] = rand()%10;

}

 

CArray::~CArray() // 소멸자

{

             delete[] ary;

}

 

CArray::CArray(const CArray &CA) // 복사 생성자

{

             count = CA.count;

             ary = new int[count];

 

             for(int i=0;i<count;i++)

                   ary[i] = CA.ary[i];

}

 

CArray &CArray::operator=(const CArray &CA) // 대입(=)  연산자 오버로딩

{

             count = CA.count;

             delete[] ary;

 

             ary = new int[count];

 

             for(int i=0;i<count;i++)

                           ary[i] = CA.ary[i];

 

             return *this;

}

 

CArray CArray::operator+(const CArray &CA) // + 연산자 오버로딩

{

             int c = count + CA.count;

             int i=0;

 

             CArray temp(c);

 

             for(;i<count;i++)

                   temp.ary[i] = ary[i];

 

             for(int j=0;i<c;i++,j++)

                   temp.ary[i] = CA.ary[j];

 

             return temp;

}

 

int &CArray::operator[](int index) // 배열 첨자 오버로딩

{

             int tmp;

 

             if(!((index>=0) && (index<count)))

             {

                           cout << "index Range Error (문제: 배열 인덱스 체크 범위 판별)" << endl;

                           return tmp;

             }

 

             return ary[index];

}

 

ostream &operator<<(ostream &out, CArray &CA) // 출력(<< ) 연산자 오버로딩

{

             for(int i=0;i<CA.count;i++)

                   out << CA.ary[i] << "\t";

 

             return out;

}

 

 

int main()

{

             srand((unsigned) time(NULL));

 

             CArray Ary1(5);

             Ary1[0] = 5;

             Ary1[1] = 7;

             Ary1[5] = 9; // 에러가 발생하는 경우! 인덱스 범위 초과 체크!

 

             return 0;

}

 

 

================================================================================================