제 12 장 . 사용자 정의형으로서의 클래스

25
제 12 제 . 제제제 제제제제제제제 제제제 2011-1 제제 1 제제제제제제제제제제 (C++)

Upload: hakeem-sampson

Post on 30-Dec-2015

59 views

Category:

Documents


0 download

DESCRIPTION

제 12 장 . 사용자 정의형으로서의 클래스. 학습 목표. 클래스를 기본형과 비슷한 방법으로 다룰 수 있게 하는 사용자 정의 형으로써의 기능을 알아본다. 클래스의 객체에 대해서 연산자를 사용할 수 있게 하는 연산자 오버로딩 기능에 대해서 알아본다. 연산자 오버로딩을 구현하기 위한 연산자 함수를 정의하는 방법과 주의 사항을 알아본다. 클래스 형을 특정 데이터 형으로 변환하는 변환 연산자를 구현하고 사용하는 알아본다. C++의 형 변환 연산자에 대해서 알아본다. 연산자 오버로딩. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 제  12 장 .  사용자 정의형으로서의 클래스

제 12 장 . 사용자 정의형으로서의 클래스

2011-1 학기 1프로그래밍언어및실습 (C++)

Page 2: 제  12 장 .  사용자 정의형으로서의 클래스

학습 목표

클래스를 기본형과 비슷한 방법으로 다룰 수 있게 하는 사용자 정의 형으로써의 기능을 알아본다 .

클래스의 객체에 대해서 연산자를 사용할 수 있게 하는 연산자 오버로딩 기능에 대해서 알아본다 .

연산자 오버로딩을 구현하기 위한 연산자 함수를 정의하는 방법과 주의 사항을 알아본다 .

클래스 형을 특정 데이터 형으로 변환하는 변환 연산자를 구현하고 사용하는 알아본다 .

C++ 의 형 변환 연산자에 대해서 알아본다 .

프로그래밍언어및실습 (C++) 22011-1 학기

Page 3: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 오버로딩

기본형에 대해서 사용하는 연산자의 의미를 확대해서 클래스 형에 대해서도 사용할 수 있도록 만드는 기능

프로그래밍언어및실습 (C++) 32011-1 학기

Page 4: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 오버로딩의 필요성

프로그래밍언어및실습 (C++) 4

class String {...public: bool IsEqual(const String& s); // 문자열의 내용이 같으면 true 를 리턴하는 함수};template <typename T> void f(const T& x, const T& y){ if( x == y ) // T 형의 두 변수의 값을 비교한다 . ...}int main(){ int a = 10, b = 10; f<int>(a, b); // T 가 int 형일 때 템플릿의 인스턴스화 OK String s1("abc"), s2("abc"); f<String>(s1, s2); // T 가 String 형일 때 템플릿의 인스턴스화 실패}

class String {...public: bool IsEqual(const String& s); // 문자열의 내용이 같으면 true 를 리턴하는 함수};template <typename T> void f(const T& x, const T& y){ if( x == y ) // T 형의 두 변수의 값을 비교한다 . ...}int main(){ int a = 10, b = 10; f<int>(a, b); // T 가 int 형일 때 템플릿의 인스턴스화 OK String s1("abc"), s2("abc"); f<String>(s1, s2); // T 가 String 형일 때 템플릿의 인스턴스화 실패} 2011-1 학기

Page 5: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 함수

"operator 연산자 " 의 형식으로 정의되는 함수 만일 연산자 함수가 정의 되지 않았으면 클래스의 객체에

대해 연산자를 사용하는 것은 컴파일 에러가 된다 .

프로그래밍언어및실습 (C++) 52011-1 학기

Page 6: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 함수의 정의 (1)

이항 연산자를 연산자 함수로 정의할 때는 피연산자 중 좌변이 객체가 되고 , + 연산자가 operator+

라는 멤버 함수가 되고 , 나머지 피연산자인 우변은 해당 함수의 인자가 된다 .

프로그래밍언어및실습 (C++) 62011-1 학기

Page 7: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 함수의 정의 (2)

프로그래밍언어및실습 (C++) 7

class String {...public: String operator+(const String& s) const;};

String String::operator+(const String& s) const{ char* tmp = new char[Size() + s.Size() + 1]; ::strcpy(tmp, m_str); ::strcat(tmp, s.m_str); String result(tmp); delete [] tmp; return result;}

class String {...public: String operator+(const String& s) const;};

String String::operator+(const String& s) const{ char* tmp = new char[Size() + s.Size() + 1]; ::strcpy(tmp, m_str); ::strcat(tmp, s.m_str); String result(tmp); delete [] tmp; return result;}

2011-1 학기

Page 8: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 함수의 구현

연산자 함수의 구현 클래스의 멤버 함수로 정의하는 방법 멤버 함수가 아닌 전역 함수로 정의하는 방법

이항 연산자 오버로딩 연산자 함수를 클래스의 멤버 함수로 정의하면 피연산자 중

하나가 클래스의 객체가 되므로 연산자 함수의 인자의 개수는 하나가 된다 .

연산자 함수를 전역 함수로 정의하면 피연산자가 모두 연산자 함수의 인자가 되므로 연산자 함수는 두 개의 인자를 갖게 된다 .

프로그래밍언어및실습 (C++) 82011-1 학기

Page 9: 제  12 장 .  사용자 정의형으로서의 클래스

멤버 함수로 정의 (1)

이항 연산자의 경우 피연산자 중 좌변을 객체로 잡으면 , 연산자가 객체가 속한 클래스의 멤버 함수가 되고 , 남은 피연산자가 연산자 함수의 인자가 된다 . 연산자 함수를 정의할 때 연산자 함수의 리턴형은 연산의

결과에 따라서 결정된다 .

프로그래밍언어및실습 (C++) 92011-1 학기

Page 10: 제  12 장 .  사용자 정의형으로서의 클래스

멤버 함수로 정의 (2)

프로그래밍언어및실습 (C++) 10

class String{ ...public: bool operator==(const String& s) const; bool operator!=(const String& s) const;};

bool String::operator==(const String& s) const{ return ::strcmp(m_str, s.m_str) == 0 ? true : false;}

bool String::operator!=(const String& s) const{ return ::strcmp(m_str, s.m_str) ? true : false;}

class String{ ...public: bool operator==(const String& s) const; bool operator!=(const String& s) const;};

bool String::operator==(const String& s) const{ return ::strcmp(m_str, s.m_str) == 0 ? true : false;}

bool String::operator!=(const String& s) const{ return ::strcmp(m_str, s.m_str) ? true : false;}2011-1 학기

Page 11: 제  12 장 .  사용자 정의형으로서의 클래스

전역 함수로 정의 (1)

피연산자 중 좌변이 객체가 아니라면 연산자 함수를 전역 함수로 정의한다 . 연산자의 피연산자 수와 연산자 함수의 인자의 개수가 항상

같다 .

프로그래밍언어및실습 (C++) 112011-1 학기

Page 12: 제  12 장 .  사용자 정의형으로서의 클래스

전역 함수로 정의 (2)

프로그래밍언어및실습 (C++) 12

class String{ ...friend String operator+(const char* s1, const String& s2);};

String operator+(const char* s1, const String& s2){ char* tmp = new char[::strlen(s1) + s2.Size() + 1]; ::strcpy(tmp, s1); ::strcat(tmp, s2.m_str); String result(tmp); delete[] tmp; return result;}

class String{ ...friend String operator+(const char* s1, const String& s2);};

String operator+(const char* s1, const String& s2){ char* tmp = new char[::strlen(s1) + s2.Size() + 1]; ::strcpy(tmp, s1); ::strcat(tmp, s2.m_str); String result(tmp); delete[] tmp; return result;}

2011-1 학기

Page 13: 제  12 장 .  사용자 정의형으로서의 클래스

삽입 연산자 오버로딩

출력에 사용되는 << 연산자를 오버로딩하려면 전역 함수로 정의한다 .

프로그래밍언어및실습 (C++) 132011-1 학기

Page 14: 제  12 장 .  사용자 정의형으로서의 클래스

연산자 오버로딩의 일반적인 규칙 연산자 오버로딩을 할 때 새로운 연산자를 정의할 수는 없다 . 예를 들어 ‘ #’ 을

새로운 연산자로 정의하는 것은 잘못이다 . 연산자의 우선 순위 , 피연산자의 개수 , 결합 방향 등을 변경할 수 없다 . 기본형에 대해서는 연산자 오버로딩할 수 없다 . 연산자 오버로딩은 반드시 클래스

형에 대해서만 가능하다 . 연산자 함수는 반드시 클래스의 멤버 함수 또는 전역 함수로 구현해야 한다 . 단항 연산자에 대한 연산자 함수를 멤버 함수로 정의하면 인자 없는 함수로 정의된

다 . 만일 전역 함수로 정의하면 인자가 하나인 함수로 정의된다 . 이항 연산자에 대한 연산자 함수를 멤버 함수로 정의하면 인자가 하나인 함수로

정의된다 . 만일 전역 함수로 정의하면 인자가 두 개인 함수로 정의된다 . 연산자 함수는 디폴트 인자를 가질 수 없다 . 대입 연산자를 제외한 모든 연산자 함수를 상속받을 수 있다 . = 연산자 , () 연산자 , [] 연산자 , -> 연산자는 반드시 연산자 함수를 멤버 함수로

정의해야 한다 . . 연산자 , .* 연산자 , :: 연산자 , ?: 연산자 , # 연산자 , ## 연산자는 오버로딩할 수

없다 .

프로그래밍언어및실습 (C++) 142011-1 학기

Page 15: 제  12 장 .  사용자 정의형으로서의 클래스

클래스 형 변환

특정 데이터 형에서 클래스 형으로의 형 변환은 변환 생성자에 의해서 처리된다 .

클래스 형에서 다른 데이터 형으로의 형 변환이 필요할 때는 변환 연산자가 사용된다 .

프로그래밍언어및실습 (C++) 152011-1 학기

Page 16: 제  12 장 .  사용자 정의형으로서의 클래스

변환 연산자 함수

변환 연산자 함수는 “ operator 데이터 형” 형태의 이름을 갖는 함수이다 . 리턴형이 없으며 , 특별히 void 라고 지정하지도 않는다 . 항상 인자 없는 함수로 정의된다 .

프로그래밍언어및실습 (C++) 162011-1 학기

Page 17: 제  12 장 .  사용자 정의형으로서의 클래스

변환 연산자 함수의 예

프로그래밍언어및실습 (C++) 17

class String{ ...public: operator const char*() const;};

String::operator const char*() const{ return m_str;}

void Test(const char* s){ cout << " 문자열 : " << (::strlen(s) == 0 ? " 없음 " : s) << "\n";}

int main(){ String str1; Test(str1); // 변환 연산자 호출

const char* str2 = str1; // 변환 연산자 호출}

class String{ ...public: operator const char*() const;};

String::operator const char*() const{ return m_str;}

void Test(const char* s){ cout << " 문자열 : " << (::strlen(s) == 0 ? " 없음 " : s) << "\n";}

int main(){ String str1; Test(str1); // 변환 연산자 호출

const char* str2 = str1; // 변환 연산자 호출}

2011-1 학기

Page 18: 제  12 장 .  사용자 정의형으로서의 클래스

C++ 의 형 변환 연산자

C 의 형 변환 연산자의 문제점 형 변환의 의도를 알기가 어렵다 .

C++ 의 형 변환 연산자 const_cast static_cast dynamic_cast reinterpret_cast

프로그래밍언어및실습 (C++) 182011-1 학기

Page 19: 제  12 장 .  사용자 정의형으로서의 클래스

const_cast

const 변수에서 const 속성을 제거하기 위한 형 변환에 사용

프로그래밍언어및실습 (C++) 19

String s1(“abc”);

const String* pStr1 = &s1;

pStr1->Set(“def”); // pStr1 이 const String* 형이므로 컴파일 에러

String* pStr2 = const_cast<String*>(pStr1); // const 속성을 제거함pStr2->Set(“def”); // pStr2 이 const String* 형이 아니므로 OK

String s1(“abc”);

const String* pStr1 = &s1;

pStr1->Set(“def”); // pStr1 이 const String* 형이므로 컴파일 에러

String* pStr2 = const_cast<String*>(pStr1); // const 속성을 제거함pStr2->Set(“def”); // pStr2 이 const String* 형이 아니므로 OK

2011-1 학기

Page 20: 제  12 장 .  사용자 정의형으로서의 클래스

static_cast

컴파일 시 자동 형 변환이 가능한지 검사 형 변환 가능한 경우에는 형 변환을 수행하고 만일 형 변환할

수 없는 경우에는 컴파일 에러를 발생

프로그래밍언어및실습 (C++) 20

class Shape {

...

};

class Rectangle : public Shape {

...

};

Rectangle r1;

Shape *pShape = static_cast<Shape*>(&r1); // OK;

Rectangle *pRect = static_cast<Rectangle*>(pShape); // 컴파일 에러

class Shape {

...

};

class Rectangle : public Shape {

...

};

Rectangle r1;

Shape *pShape = static_cast<Shape*>(&r1); // OK;

Rectangle *pRect = static_cast<Rectangle*>(pShape); // 컴파일 에러

2011-1 학기

Page 21: 제  12 장 .  사용자 정의형으로서의 클래스

dynamic_cast

실행 시간에 형 변환 가능하지 검사 만일 형 변환 가능하면 형 변환을 수행하고 형 변환할 수

없는 경우에는 0 을 리턴하거나 예외를 발생

프로그래밍언어및실습 (C++) 21

Shape* pShape = NULL;

int choice;

cin >> choice;

switch(choice)

{

case 1 : pShape = new Shape; break;

case 2 : pShape = new Rectangle; break;

}

Rectangle *pRect = dynamic_cast<Rectangle*>(pShape);

if( pRect != NULL )

pRect->GetWidth();

Shape* pShape = NULL;

int choice;

cin >> choice;

switch(choice)

{

case 1 : pShape = new Shape; break;

case 2 : pShape = new Rectangle; break;

}

Rectangle *pRect = dynamic_cast<Rectangle*>(pShape);

if( pRect != NULL )

pRect->GetWidth();2011-1 학기

Page 22: 제  12 장 .  사용자 정의형으로서의 클래스

RTTI (1)

dynamic_cast 연산자를 사용하려면 C++ 의 RTTI 기능을 사용해야 한다 .

RTTI(Run-Time Type Information) 실행 시간에 객체의 클래스 형에 대한 정보를 구할 수 있는

기능 typeid 연산자와 type_info 클래스 제공

프로그래밍언어및실습 (C++) 22

Rectangle *pRect = new Rectangle;Shape *pShape = pRect;cout << typeid( pShape ).name() << endl; // class Shape * 출력cout << typeid( *pShape ).name() << endl; // class Rectangle 출력cout << typeid( pRect ).name() << endl; // class Rectangle * 출력cout << typeid( *pRect ).name() << endl; // class Rectangle 출력delete pRect;

Rectangle *pRect = new Rectangle;Shape *pShape = pRect;cout << typeid( pShape ).name() << endl; // class Shape * 출력cout << typeid( *pShape ).name() << endl; // class Rectangle 출력cout << typeid( pRect ).name() << endl; // class Rectangle * 출력cout << typeid( *pRect ).name() << endl; // class Rectangle 출력delete pRect;

2011-1 학기

Page 23: 제  12 장 .  사용자 정의형으로서의 클래스

RTTI (2)

typeid 연산자 변수나 객체의 형 정보를 저장하는 type_info 클래스

객체의 레퍼런스를 리턴 type_info 클래스

데이터 형을 비교하는 == 연산자 함수나 != 연산자 함수 , 데이터 형 이름을 문자열로 리턴하는 name 함수를 제공

type_info 클래스는 컴파일러에 의해서 내부적으로 정의되며 type_info 클래스의 객체를 생성하는 유일한 방법은 typeid 연산자를 이용하는 것이다 .

프로그래밍언어및실습 (C++) 232011-1 학기

Page 24: 제  12 장 .  사용자 정의형으로서의 클래스

reinterpret_cast

강제 형 변환을 수행

프로그래밍언어및실습 (C++) 24

unsigned short Hash( void *p ){ unsigned int val = reinterpret_cast<unsigned int>( p ); return ( unsigned short )( val ^ (val >> 16));}

unsigned short Hash( void *p ){ unsigned int val = reinterpret_cast<unsigned int>( p ); return ( unsigned short )( val ^ (val >> 16));}

2011-1 학기

Page 25: 제  12 장 .  사용자 정의형으로서의 클래스

정리 클래스의 객체에 대해서 연산자를 사용할 수 있도록 만드는

기능을 연산자 오버로딩이라고 한다 . 연산자 오버로딩은 연산자 함수에 의해서 구현된다 . 연산자 함수는 클래스의 멤버 함수로 정의할 수도 있고 , 전역

함수로 정의할 수도 있다 . 클래스 형과 기본형 사이의 형 변환에 변환 생성자와 변환

연산자가 이용된다 . 클래스 형을 다른 데이터 형으로 변환하려면 변환 연산자를

정의한다 . C++ 은 형 변환의 의미를 명확히 구분해서 사용할 수 있도록 형

변환 연산자인 const_cast, static_cast, dynamic_cast, reinterpret_cast 연사자를 제공한다 .

프로그래밍언어및실습 (C++) 252011-1 학기