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

Post on 30-Dec-2015

59 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

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

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

학습 목표

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

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

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

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

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

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

연산자 오버로딩

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

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

연산자 오버로딩의 필요성

프로그래밍언어및실습 (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 학기

연산자 함수

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

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

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

연산자 함수의 정의 (1)

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

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

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

연산자 함수의 정의 (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 학기

연산자 함수의 구현

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

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

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

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

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

멤버 함수로 정의 (1)

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

결과에 따라서 결정된다 .

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

멤버 함수로 정의 (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 학기

전역 함수로 정의 (1)

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

같다 .

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

전역 함수로 정의 (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 학기

삽입 연산자 오버로딩

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

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

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

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

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

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

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

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

없다 .

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

클래스 형 변환

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

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

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

변환 연산자 함수

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

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

변환 연산자 함수의 예

프로그래밍언어및실습 (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 학기

C++ 의 형 변환 연산자

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

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

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

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 학기

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 학기

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 학기

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 학기

RTTI (2)

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

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

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

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

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

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 학기

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

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

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

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

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

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

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

top related