8. 상속과다형성 (polymorphism) 상속된객체와포인터 / 참조자의관계 정적바인딩과동적바인딩 virtual 소멸자 Jong Hyuk Park
상속의조건 public 상속은 is-a 관계가성립되도록하자. 일반화 ParttimeStd 구체화 2
상속의조건 잘못된상속의예 현실세계와완전히동떨어진모델이형성됨 3
상속의조건 HAS-A( 소유 ) 관계에의한상속! 경찰은몽둥이를소유한다 The Police have a cudgel. 상속은소유를표현하기위해서도사용함 4
#include <iostream> using std::endl; using std::cout; 예제 1 class Cudgel // 몽둥이 void Swing() cout<<"swing a cudgel!"<<endl; int main() Police pol; pol.useweapon(); class Police : public Cudgel // 몽둥이를소유하는경찰 return 0; void UseWeapon() Swing(); Police is a Cudgel (X) Police has a Cudgel (O)
상속의조건 HAS-A 에의한상속그리고대안! 포함관계를통해서소유관계를표현 객체멤버에의한포함관계의형성 예제 2 객체포인터멤버에의한포함관계의형성 예제 3 6
상속의조건 /* 예제2 */ class Cudgel // 몽둥이 void Swing() cout<<"swing a cudgel!"<<endl; class Police // 몽둥이를소유하는경찰 Cudgel cud; // 클래스객체멤버 or 객체멤버 void UseWeapon() cud.swing(); int main() Police pol; pol.useweapon(); return 0; 7
8 상속의조건 /* 예제3 */ class Cudgel // 몽둥이 void Swing() cout<<"swing a cudgel!"<<endl; class Police // 몽둥이를소유하는경찰 Cudgel* cud; Police() cud=new Cudgel; ~Police() delete cud; void UseWeapon() cud->swing(); int main() Police pol; pol.useweapon(); return 0;
상속된객체와포인터 / 참조자의관계 Jong Hyuk Park
상속된객체와포인터관계 객체포인터 객체의주소값을저장할수있는포인터 AAA 클래스의포인터는 AAA 객체의주소뿐만아니라 AAA 클래스를상속하는 Derived 클래스의객체의주소값도저장가능 AAA 클래스의참조자는 AAA 객체뿐만아니라 AAA 클래스를상속하는 Derived 클래스의객체도참조가능 10
객체의포인터예 CPointer1.cpp #include <iostream> int main(void) using std::endl; using std::cout; Person* p1=new Person; class Person Person* p2=new Student; t Person* p3=new PartTimeStd; void Sleep() cout<<"sleep"<<endl; <<endl; p1->sleep(); p2->sleep(); class Student : public Person p3->sleep(); int main(void) return 0; Person* p1=new PartTimeStd; void Study() Student* p2=new PartTimeStd; cout<<"study"<<endl; PartTimeStd * p3=new PartTimeStd; class PartTimeStd : public Student p1->sleep(); p2->sleep(); 11 void Work() cout<<"work"<<endl; p3->sleep(); return 0;
상속된객체의포인터, 참조자 객체포인터의권한 포인터를통해서접근할수있는객체멤버의영역 AAA 클래스의객체포인터는 AAA 클래스의멤버와 AAA 클래스가상속받은 Base 클래스의멤버만접근가능 AAA 클래스의참조자는 AAA 클래스의멤버와 AAA 클래스가상속받은 Base 클래스의멤버만접근가능 12
CPointer2.cpp 13 객체포인터의권한예 #include <iostream> using std::endl; using std::cout; class Person void Sleep() cout<<"sleep"<<endl; class Student : public Person int main(void) id Person* p3=new PartTimeStd; void Study() cout<<"study"<<endl; " dl p3->sleep(); p3->study(); //! 에러 p3->work(); //! 에러 class PartTimeStd : public Student void Work() cout<<"work"<<endl; return 0;
상속된객체와참조관계 객체의레퍼런스 객체를참조할수있는레퍼런스 클래스포인터의특성과일치 CReference1. cpp 객체레퍼런스의권한 객체를참조하는레퍼런스의권한 클래스포인터의권한과일치 CReference2. cpp 14
CReference1. cpp #include <iostream> 객체의참조자예 using std::endl; using std::cout; class Person void Sleep() cout<<"sleep"<<endl; class Student : public Person void Study() cout<<"study"<<endl; <<endl; class PartTimeStd : public Student void Work() cout<<"work"<<endl; <<endl; 15 int main(void) PartTimeStd p; Student& ref1=p; Person & ref2=p; p.sleep(); ref1.sleep(); ref2.sleep(); return 0;
객체참조자의권한예 CReference2. cpp #include <iostream> using std::endl; using std::cout; class Person void Sleep() cout<<"sleep"<<endl; class Student : public Person void Study() cout<<"study"<<endl; int main(void) PartTimeStd p; Person& ref=p; class PartTimeStd : public Student ref.sleep(); void Work() cout<<"work"<<endl; ref.study(); //! 에러 ref.work(); //! 에러 return 0; 16
정적바인딩과동적바인딩 Jong Hyuk Park
오버라이딩 (overriding) 오버라이딩 (Overriding) 의이해 Base 클래스에선언된멤버와같은형태의멤버를 Derived 클래스에서선언 Base 클래스의멤버를가리는효과! 보는시야 (Pointer) 에따라서달라지는효과! Overriding1.cpp, Overriding2.cpp 18
오버라이딩 (overriding) 베이스클래스에서선언된함수를파생클래스에서다시선언 Overriding1.cpp #include <iostream> using std::endl; using std::cout; class AAA void fct() cout<<"aaa"<<endl; int main(void) BBB b; b.fct(); return 0; 19 class BBB : public AAA void fct() cout<<"bbb"<<endl; BBB
Overriding2.cpp #include <iostream> using std::endl; using std::cout; class AAA void fct() cout<<"aaa"<<endl; class BBB : public AAA void fct() cout<<"bbb"<<endl; 오버라이딩예 int main(void) BBB* b=new BBB; b->fct(); AAA* a=b; a->fct(); delete b; return 0; BBB AAA 20
가상함수 (virtual function) 멤버함수를가상 (virtual) 로선언 오버라이딩되는경우의특징은? - Overriding3.cpp Virtual 의특성도상속된다. - Overriding4.cpp 21
가상함수예 Overriding3.cpp #include <iostream> using std::endl; using std::cout; class AAA virtual void fct() // 가상함수 cout<<"aaa"<<endl; class BBB : public AAA void fct() cout<<"bbb"<<endl; <<endl; int main(void) BBB* b=new BBB; b->fct(); BBB BBB AAA* a=b; a->fct(); delete b; return 0; 22
가상함수특성상속예 Overriding4.cpp #include <iostream> using std::endl; using std::cout; class AAA virtual void fct() // 가상함수 cout<<"aaa"<<endl; class BBB : public AAA void fct() // virtual void fct() cout<<"bbb"<<endl; class CCC : public BBB void fct() cout<<"ccc"<<endl; <<endl; 23 int main(void) id) BBB* b=new BBB; b->fct(); CCC CCC AAA* a=b; a->fct(); delete b; return 0;
바인딩 (binding) 과다형성 바인딩 정적바인딩 (static binding) 컴파일시 (compile-time) 호출되는함수를결정 동적바인딩 (dynamic binding) 실행시 (run-time) 호출되는함수를결정 오버라이딩된함수의호출 Overriding5.cpp 24
바인딩예 #include <iostream> using std::endl; using std::cout; class AAA virtual void fct() // 가상함수 cout<<"aaa"<<endl; class BBB : public AAA void fct() cout<<"bbb"<<endl; int main(void) BBB b; b.fct(); // 정적바인딩 ` BBB BBB AAA* a=new BBB; a->fct(); // 동적바인딩 delete b; return 0; 25
오버라이딩된함수호출예 #include <iostream> using std::endl; using std::cout; class AAA virtual void fct() cout<<"aaa"<<endl; <<endl; class BBB : public AAA void fct() AAA::fct(); // 방법 1. cout<<"bbb"<<endl; int main(void) AAA* a=new BBB; cout<<" 첫번째시도 "<<endl; a->fct(); cout<<" 두번째시도 "<<endl; a->aaa::fct(); // 방법 2. return 0; 첫번째시도 AAA BBB 두번째시도 AAA 26
바인딩 (binding) 과다형성 다형성 (polymorphism) 같은모습의형태가다른특성 a->fct() ft() 예 a라는포인터 ( 모습 ) 가가리키는대상에따라호출되는함수 ( 형태 ) 가다름 함수오버로딩, 동적바인딩등이다형성의예 27
순수가상함수 순수가상함수 (pure virtual function) 베이스클래스에서는어떤동작도정의되지않고함수의선언만을하는가상함수 순수가상함수를선언하고파생클래스에서이가상함수를중복정의하지않으면컴파일시에에러가발생 하나이상의멤버가순수가상함수인클래스를추상클래스 (abstract class) 라함 완성된클래스가아니기때문에객체화되지않는클래스 베이스클래스에서다음과같은형식으로선언 virtual 자료형함수명 ( 인수리스트 ) = 0; 28
순수가상함수예 (1) #include <iostream> using std::endl; using std::cout; class Date // 베이스클래스 protected:` int year,month,day; Date(int y,int m,int d) year = y; month = m; day = d; virtual void print() = 0; // 순수가상함수 class Adate : public Date // 파생클래스 Adate Adate(int y,int m,int d) : Date(y,m,d) /* no operation */ void print() // 가상함수 cout << year << '.' << month << '.' << day << ".\n"; class Bdate : public Date // 파생클래스 Bdate Bdate(int y,int m,int d) : Date(y,m,d) /* no operation */ void print(); // 가상함수 29 void Bdate::print() static char *mn[] = "Jan.", "Feb.", "Mar.", "Apr.", "May", "June""July", July, "Aug Aug. ","Sep Sep. ","Oct Oct. ", "Nov.","Dec." cout << mn[month-1] << ' ' << day << ' ' << year << '\n'; int main() Adate a(1994,6,1); 1) Bdate b(1945,8,15); Date &r1 = a, &r2 = b; // 참조자 r1.print(); r2.print(); return 0; 1994.6.1. 1 Aug. 15 1945
virtual 소멸자 Jong Hyuk Park
virtual 소멸자 파생클래스를가리키는베이스클래스의포인터가가리키는객체의소멸시에는파생클래스의소멸자를호출하지않음 virtual 소멸자 객체소멸시베이스클래스뿐만아니라파생클래스의소멸자도호출 소멸자앞에 virtual 키워드 31
32 virtual 소멸자필요성예 #include <iostream> using std::endl; using std::cout; class AAA char* str1; AAA(char* _str1) str1= t1 new char[strlen(_str1)+1]; [tl t 1] strcpy(str1, _str1); ~AAA() cout<<" ~AAA() call!"<<endl; delete []str1; virtual void ShowString() cout<<str1<<' '; class BBB : public AAA char* str2; BBB(char* _str1, char* _str2) : AAA(_str1) str2= new char[strlen(_str2)+1]; str2)+1]; strcpy(str2, _str2); ~BBB() cout<<"~bbb() call!"<<endl; delete []str2; virtual void ShowString() AAA::ShowString(); cout<<str2<<endl; int main() AAA * a=new BBB("Good", "evening"); BBB * b=new BBB("Good", "morning"); a->showstring(); b->showstring(); cout<<"-----객체소멸직전----"<<endl; delete a; // AAA 소멸자만호출 delete b; // BBB,AAA 소멸자호출 return 0; Good evening Good morning -----객체소멸직전---- ~AAA() call! ~BBB() call! ~AAA() call!
Virtual 소멸자의필요성 상속하고있는클래스객체소멸문제점 33
34 virtual 소멸자예 #include <iostream> using std::endl; using std::cout; class AAA char* str1; AAA(char* _str1) str1= t1 new char[strlen(_str1)+1]; [tl t 1] strcpy(str1, _str1); virtual ~AAA() cout<<" ~AAA() call!"<<endl; delete []str1; virtual void ShowString() cout<<str1<<' '; class BBB : public AAA char* str2; BBB(char* _str1, char* _str2) : AAA(_str1) str2= new char[strlen(_str2)+1]; str2)+1]; strcpy(str2, _str2); ~BBB() cout<<"~bbb() call!"<<endl; delete []str2; virtual void ShowString() St AAA::ShowString(); cout<<str2<<endl; int main() AAA * a=new BBB("Good", "evening"); BBB * b=new BBB("Good", "morning"); a->showstring(); b->showstring(); cout<<"-----객체소멸직전----"<<endl; delete a; // BBB, AAA 소멸자만호출 delete b; // BBB,AAA 소멸자호출 return 0; Good evening Good morning -----객체소멸직전---- ~BBB() call! ~AAA() call! ~BBB() call! ~AAA() call!
Virtual 소멸자의필요성 virtual 소멸자 virtual ~AAA() cout<<"~aaa() call!"<<endl; delete []str1; 35
Jong Hyuk Park