1 6 주차 클래스상속
유전적상속과객체지향상속 2 그래요우리를꼭닮았어요 아빠의유산이다. 나를꼭닮았군 유산상속 유전적상속 : 객체지향상속 생물 동물 식물 상속받음 어류사람나무풀 유전적상속과관계된생물분류
C++ 에서의상속 (Inheritance) 3 C++ 에서의상속이란? 클래스사이에서상속관계정의 객체사이에는상속관계없음 기본클래스의속성과기능을파생클래스에물려주는것 기본클래스 (base class) - 상속해주는클래스. 부모클래스 파생클래스 (derived class) 상속받는클래스. 자식클래스 기본클래스의속성과기능을물려받고자신만의속성과기능을추가하여작성 기본클래스에서파생클래스로갈수록클래스의개념이구체화 다중상속을통한클래스의재활용성높임
4 상속의표현
상속의목적및장점 5 1. 간결한클래스작성 기본클래스의기능을물려받아파생클래스를간결하게작성 2. 클래스간의계층적분류및관리의용이함 상속은클래스들의구조적관계파악용이 3. 클래스재사용과확장을통한소프트웨어생산성향상 빠른소프트웨어생산필요 기존에작성한클래스의재사용 상속 상속받아새로운기능을확장 앞으로있을상속에대비한클래스의객체지향적설계필요
상속관계로클래스의간결화사례 6 기능이중복된 4 개의클래스 상속관계로클래스의간결화
상속선언 7 상속선언 상속접근지정. private, protected 도가능 파생클래스명 기본클래스명 class Student : public Person { // Person 을상속받는 Student 선언... ; class StudentWorker : public Student { // Student 를상속받는 StudentWorker 선언... ; Student 클래스는 Person 클래스의멤버를물려받는다. StudentWorker 클래스는 Student 의멤버를물려받는다. Student 가물려받은 Person 의멤버도함께물려받는다.
8 예제 5-1 Point 클래스를상속받는 ColorPoint 클래스만들기 #include <iostream> #include <string> using namespace std; // 2 차원평면에서한점을표현하는클래스 Point 선언 class Point { int x, y; // 한점 (x,y) 좌표값 void set(int x, int y) { this->x = x; this->y = y; void showpoint() { cout << "(" << x << "," << y << ")" << endl; ; class ColorPoint : public Point { // 2 차원평면에서컬러점을표현하는클래스 ColorPoint. Point 를상속받음 string color;// 점의색표현 void setcolor(string color) {this->color = color; void showcolorpoint(); ; void ColorPoint::showColorPoint() { cout << color << ":"; showpoint(); // Point 의 showpoint() 호출 int main() { Point p; // 기본클래스의객체생성 ColorPoint cp; // 파생클래스의객체생성 cp.set(3,4); // 기본클래스의멤버호출 cp.setcolor("red"); // 파생클래스의멤버호출 cp.showcolorpoint(); // 파생클래스의멤버호출 Red:(3,4)
파생클래스의객체구성 9 class Point { int x, y; // 한점 (x,y) 좌표값 void set(int x, int y); void showpoint(); ; class ColorPoint : public Point { // Point 를상속받음 string color; // 점의색표현 void setcolor(string color); void showcolorpoint(); ; Point p; int x int y void set() {... void showpoint() {... ColorPoint cp; int x int y void set() {... void showpoint() {... 파생클래스의객체는기본클래스의멤버포함 기본클래스멤버 string color void setcolor () {... void showcolorpoint() {... 파생클래스멤버
파생클래스에서기본클래스멤버접근 10 파생클래스에서기본클래스멤버호출 x y void set(int x, int y) { this->x= x; this->y=y; void showpoint() { cout << x << y; color void setcolor ( ) {... void showcolorpoint() { cout << color << : ; showpoint(); ColorPoint cp 객체 Point 멤버 ColorPoint 멤버
외부에서파생클래스객체에대한접근 11 x, y 는 Point 클래스의 set(), showpoint() 에서만접근가능 기본클래스멤버호출 x 3 y 4 void set(int x, int y) { this->x= x; this->y=y; void showpoint() { cout << x << y; color Red ColorPoint cp; cp.set(3, 4); cp.setcolor( Red ); cp.showcolorpoint(); main() 파생클래스멤버호출 파생클래스멤버호출 void setcolor (string color) { this->color = color; void showcolorpoint() { cout << color << : ; showpoint(); ColorPoint cp 객체
상속과객체포인터 업캐스팅 12 업캐스팅 (up-casting) 파생클래스포인터가기본클래스포인터에치환되는것 예 ) 사람을동물로봄 pder 포인터로객체 cp 의모든 public 멤버접근가능 pder int x 3 pbase pbase 포인터로기본클래스의 public 멤버만접근가능 int main() { ColorPoint cp; ColorPoint *pder = &cp; Point* pbase = pder; // 업캐스팅 int y 4 void set() {... void showpoint() {... 기본클래스멤버 pder->set(3,4); pbase->showpoint(); pder->setcolor( Red ); pder->showcolorpoint(); pbase->showcolorpoint(); // 컴파일오류 string color void setcolor () {... void showcolorpoint() {... 파생클래스멤버 (3,4) Red(3,4) cp
업캐스팅 13 생물을가리키는손가락으로컵을가리키면오류
상속과객체포인터 다운캐스팅 14 다운캐스팅 (down-casting) 기본클래스의포인터가파생클래스의포인터에치환되는것 pder pder 포인터로객체cp의모든 public 멤버접근가능 int x 3 pbase pbase 포인터로기본클래스의 public 멤버만접근가능 int main() { ColorPoint cp; ColorPoint *pder; Point* pbase = &cp; // 업캐스팅 int y 4 void set() {... void showpoint() {... 기본클래스멤버 pbase->set(3,4); pbase->showpoint(); 강제타입변환반드시필요 string color pder = (ColorPoint *)pbase; // 다운캐스팅 pder->setcolor( Red ); // 정상컴파일 pder->showcolorpoint(); // 정상컴파일 (3,4) Red(3,4) void setcolor () {... void showcolorpoint() {... cp 파생클래스멤버
protected 접근지정 15 접근지정자 private 멤버 선언된클래스내에서만접근가능 파생클래스에서도기본클래스의 private 멤버직접접근불가 public 멤버 선언된클래스나외부어떤클래스, 모든외부함수에접근허용 파생클래스에서기본클래스의 public 멤버접근가능 protected 멤버 선언된클래스에서접근가능 파생클래스에서만접근허용 파생클래스가아닌다른클래스나외부함수에서는 protected 멤버를접근할수없다.
멤버의접근지정에따른접근성 16 외부함수기본클래스다른클래스 void function() { class A { private: private 멤버 protected: protected 멤버 public 멤버 ; class C { ; class B : public A { ; 파생클래스 protected 멤버는파생클래스에접근이허용된다.
예제 5-2 protected 멤버에대한접근 17 #include <iostream> #include <string> using namespace std; class Point { protected: int x, y; // 한점 (x,y) 좌표값 void set(int x, int y); void showpoint(); ; void Point::set(int x, int y) { this->x = x; this->y = y; void Point::showPoint() { cout << "(" << x << "," << y << ")" << endl; class ColorPoint : public Point { string color; void setcolor(string color); void showcolorpoint(); bool equals(colorpoint p); ; // ColorPoint 구현 void ColorPoint::setColor(string color) { this->color = color; void ColorPoint::showColorPoint() { cout << color << ":"; showpoint(); // Point 클래스의 showpoint() 호출 bool ColorPoint::equals(ColorPoint p) { if(x == p.x && y == p.y && color == p.color) // 1 return true; else return false; int main() { Point p; // 기본클래스의객체생성 p.set(2,3); p.x = 5; p.y = 5; p.showpoint(); // 2 // 3 // 4 ColorPoint cp; // 파생클래스의객체생성 cp.x = 10; // 5 cp.y = 10; // 6 cp.set(3,4); cp.setcolor("red"); cp.showcolorpoint(); ColorPoint cp2; cp2.set(3,4); cp2.setcolor("red"); cout << ((cp.equals(cp2))?"true":"false"); // 7 오류 오류 오류
상속관계의생성자와소멸자실행 18 질문 1 파생클래스의객체가생성될때파생클래스의생성자와기본클래스의생성자가모두실행되는가? 아니면파생클래스의생성자만실행되는가? 답-둘다실행된다. 질문 2 파생클래스의생성자와기본클래스의생성자중에서어떤생성자가먼저실행되는가? 답-기본클래스의생성자가먼저실행된후파생클래스의생성자가실행된다.
생성자호출관계및실행순서 19 A() 호출 class A { A() { cout << " 생성자 A" << endl; ~A() { cout << " 소멸자 A" << endl; ; A() 실행 리턴 B() 호출 int main() { C c; // c 생성 C() 호출 return 0; // c 소멸 class B : public A { B() { cout << " 생성자 B" << endl; ~B() { cout << " 소멸자 B" << endl; ; class C : public B { C() { cout << " 생성자 C" << endl; ~C() { cout << " 소멸자 C"<< endl; ; B() 실행 리턴 C() 실행 생성자 A 생성자 B 생성자 C 소멸자 C 소멸자 B 소멸자 A 컴파일러는이곳에생성자 B() 를호출하는코드삽입
소멸자의실행순서 20 파생클래스의객체가소멸될때 파생클래스의소멸자가먼저실행되고 기본클래스의소멸자가나중에실행
21 컴파일러에의해묵시적으로기본클래스의생성자를선택하는경우 파생클래스의생성자에서기본클래스의기본생성자호출 컴파일러는묵시적으로기본클래스의기본생성자를호출하도록컴파일함 class A { A() { cout << " 생성자 A" << endl; A(int x) { cout << " 매개변수생성자 A" << x << endl; ; int main() { B b; class B : public A { B() { // A() 호출하도록컴파일됨 cout << " 생성자 B" << endl; ; 생성자 A 생성자 B
기본클래스에기본생성자가없는경우 22 class A { 컴파일러가 B() 에대한짝으로 A() 를찾을수없음 ; A(int x) { cout << " 매개변수생성자 A" << x << endl; int main() { B b; class B : public A { B() { // A() 호출하도록컴파일됨 cout << " 생성자 B" << endl; ; 컴파일오류발생!!! error C2512: A' : 사용할수있는적절한기본생성자가없습니다.
23 매개변수를가진파생클래스의생성자는묵시적으로기본클래스의기본생성자선택 파생클래스의매개변수를가진생성자가기본클래스의기본생성자호출 컴파일러는묵시적으로기본클래스의기본생성자를호출하도록컴파일함 int main() { B b(5); class A { A() { cout << " 생성자 A" << endl; A(int x) { cout << " 매개변수생성자 A" << x << endl; ; class B : public A { B() { // A() 호출하도록컴파일됨 cout << " 생성자 B" << endl; B(int x) { // A() 호출하도록컴파일됨 cout << 매개변수생성자 B" << x << endl; ; 생성자 A 매개변수생성자 B5
24 파생클래스의생성자에서명시적으로기본클래스의생성자선택 파생클래스의생성자가명시적으로기본클래스의생성자를선택호출함 class A { A() { cout << " 생성자 A" << endl; A(int x) { cout << " 매개변수생성자 A" << x << endl; ; int main() { B b(5); A(8) 호출 B(5) 호출 class B : public A { B() { // A() 호출하도록컴파일됨 cout << " 생성자 B" << endl; B(int x) : A(x+3) { cout << 매개변수생성자 B" << x << endl; ; 매개변수생성자 A8 매개변수생성자 B5
컴파일러의기본생성자호출코드삽입 25 class B { B() : A() { cout << " 생성자 B" << endll; ; 컴파일러가묵시적으로삽입한코드 컴파일러가묵시적으로삽입한코드 B(int x) : A() { cout << " 매개변수생성자 B" << x << endll;
예제 5-3 TV, WideTV, SmartTV 생성자매개변수전달 #include <iostream> #include <string> using namespace std; class TV { int size; // 스크린크기 TV() { size = 20; ; 32 TV(int size) { this->size = size; int getsize() { return size; class WideTV : public TV { // TV를상속받는 WideTV bool videoin; 32 true WideTV(int size, bool videoin) : TV(size) { this->videoin = videoin; bool getvideoin() { return videoin; ; int main() { // 32 인치크기에 "192.0.0.1" 의인터넷주소를가지는스마트 TV 객체생성 SmartTV htv("192.0.0.1", 32); cout << "size=" << htv.getsize() << endl; cout << "videoin=" << boolalpha << htv.getvideoin() << endl; cout << "IP="htv.getIpAddr() << endl; boolalpha는불린값을 true, false로출력되게하는조작자 size=32 videoin=true IP=192.0.0.1 class SmartTV : public WideTV { // WideTV를상속받는 SmartTV string ipaddr; // 인터넷주소 SmartTV(string ipaddr, int size) : WideTV(size, true) { this->ipaddr = ipaddr; 32 string getipaddr() { return ipaddr; ; 192.0.0.1 26 int size 32 bool videoin true string ipaddr 192.0.0.1 htv TV 영역 WideTV 영역 SmartTV 영역
연습 ) 상속관계의생성자매개변수처리예 27 class A { int x; A() { x = 0; A(int x) { this->x = x; ; 실행 A(8) 호출 int main() { C c(3,5,2); B(3,5) 호출 C(3,5,2) 호출 class B : public A { int y; B (int x, int y) : A(x+5) { this->y = y; 실행 ; class C : public B { int m; C(int x, int y, int z) : B(x, y) { m = x*y*z; 실행 ; 리턴 리턴 x=? y=? m=?
상속지정 28 상속지정 상속선언시 public, private, protected 의 3 가지중하나지정 기본클래스의멤버의접근속성을어떻게계승할지지정 public 기본클래스의 protected, public 멤버속성을그대로계승 private 기본클래스의 protected, public 멤버를 private 으로계승 protected 기본클래스의 protected, public 멤버를 protected 로계승
29 상속시접근지정에따른멤버의접근지정속성변화 class Base { private: int a; protected: int b; int c; ; public 상속 class Derived : public Base {... // Derived 멤버 ; 상속후 Derived protected: int b; int c;... // Derived 멤버 Base 영역 Derived 영역 class Base { private: int a; protected: int b; int c; ; protected 상속 class Derived : protected Base {... // Derived 멤버 ; 상속후 Derived protected: int b; int c;... // Derived 멤버 Base 영역 Derived 영역 class Base { private: int a; protected: int b; int c; ; private 상속 class Derived : private Base {... // Derived 멤버 ; 상속후 Derived private: int b; int c;... // Derived 멤버 Base 영역 Derived 영역
예제 5-4 private 상속사례 30 다음에서컴파일오류가발생하는부분을찾아라. #include <iostream> using namespace std; class Base { int a; protected: void seta(int a) { this->a = a; void showa() { cout << a; ; class Derived : private Base { int b; protected: void setb(int b) { this->b = b; void showb() { cout << b; ; int main() { Derived x; x.a = 5; x.seta(10); x.showa(); x.b = 10; x.setb(10); x.showb(); 컴파일오류 1, 2, 3, 4, 5 // 1 // 2 // 3 // 4 // 5 // 6
예제 5-5 protected 상속사례 31 다음에서컴파일오류가발생하는부분을찾아라. #include <iostream> using namespace std; class Base { int a; protected: void seta(int a) { this->a = a; void showa() { cout << a; ; class Derived : protected Base { int b; protected: void setb(int b) { this->b = b; void showb() { cout << b; ; int main() { Derived x; x.a = 5; x.seta(10); x.showa(); x.b = 10; x.setb(10); x.showb(); 컴파일오류 1, 2, 3, 4, 5 // 1 // 2 // 3 // 4 // 5 // 6
예제 5-6 상속이중첩될때접근지정사례 32 다음에서컴파일오류가발생하는부분을찾아라. #include <iostream> using namespace std; class Base { int a; protected: void seta(int a) { this->a = a; void showa() { cout << a; ; class Derived : private Base { int b; protected: void setb(int b) { this->b = b; void showb() { seta(5); // 1 showa(); // 2 cout << b; ; class GrandDerived : private Derived { int c; protected: void setab(int x) { seta(x); // 3 showa(); // 4 setb(x); // 5 ; 컴파일오류 3, 4
기기의컨버전스와 C++ 의다중상속 33 class TextEditor class Interpreter 컨버전스 다중상속 class TextEditorInterpreter
다중상속선언및멤버호출 34 class MP3 { void play(); void stop(); ; class MobilePhone { bool sendcall(); bool receivecall(); bool sendsms(); bool receivesms(); ; 상속받고자하는기본클래스를나열한다. 다중상속선언 class MusicPhone : public MP3, public MobilePhone { // 다중상속선언 void dial(); ; 다중상속활용 void MusicPhone::dial() { play(); // mp3 음악을연주시키고 sendcall(); // 전화를건다. MP3::play() 호출 MobilePhone::sendCall() 호출 다중상속활용 int main() { MusicPhone hanphone; hanphone.play(); // MP3의멤버 play() 호출 hanphone.sendsms(); // MobilePhone의멤버 sendsms() 호출
35 예제 5-7 Adder 와 Subtractor 를다중상속받는 Calculator 클래스작성 #include <iostream> using namespace std; class Adder { protected: int add(int a, int b) { return a+b; ; class Subtractor { protected: int minus(int a, int b) { return a-b; ; // 다중상속 class Calculator : public Adder, public Subtractor { int calc(char op, int a, int b); ; int Calculator::calc(char op, int a, int b) { int res=0; switch(op) { case '+' : res = add(a, b); break; case '-' : res = minus(a, b); break; return res; int main() { Calculator handcalculator; cout << "2 + 4 = " << handcalculator.calc('+', 2, 4) << endl; cout << "100-8 = " << handcalculator.calc('-', 100, 8) << endl; 2 + 4 = 6 100 8 = 92
다중상속의문제점 Base 의멤버가이중으로객체에삽입되는문제점. 동일한 x 를접근하는프로그램이서로다른 x 에접근하는결과를낳게되어잘못된실행오류가발생된다. 36
가상상속 37 다중상속으로인한멤버의중복문제해결 가상상속 파생클래스를선언문에서기본클래스앞에 virtual 로선언 파생클래스의객체가생성될때기본클래스의멤버는오직한번만생성 기본클래스의멤버가중복하여생성되는것을방지 class In : virtual public BaseIO { // In 클래스는 BaseIO 클래스를가상상속함... ; class Out : virtual public BaseIO { // Out 클래스는 BaseIO 클래스를가상상속함... ;
가상상속으로다중상속의모호성해결 가상상속 38