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