8장상속 - contents.kocw.or.krcontents.kocw.or.kr/document/cpp08_inheritance.pdf ·...

32
C++ 프로그래밍 입문 8장 상속 상속의 기본 개념 상속 관련 문제 제기 base 클래스의 접근 제어와 protected 멤버 상속 관계에서의 생성자와 소멸자 함수 재정의(function overriding) 디폴트 액세스 지정자와 구조체 derived 클래스로부터의 상속 다중 상속 virtual base 클래스 derived 클래스의 디폴트 복사 생성자와 디폴트 대입 연산자 private 생성자의 사용

Upload: others

Post on 21-Jun-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

C++ 프 그래 문

8 상

상 본 개

상 문제 제

base 클래스 접근 제어 protected

상 계에 생

함수 정 (function overriding)

폴트 액 스 정 조체

derived 클래스 상

다 상

virtual base 클래스

derived 클래스 폴트 복사 생 폴트 연산

private 생 사

8 상 1

1. 상 본 개

다 과 같 문제를 한 클래스 계

n 동차

Ø : 색상, 량, 현

Ø 드 : 가 하라, 춰라, 시동 켜라

n 트럭

Ø : 색상, 량, 현 , 최 량

Ø 드 : 가 하라, 춰라, 시동 켜라

n 택시

Ø : 색상, 량, 현 , , 주행거리

Ø 드 : 가 하라, 춰라, 시동 켜라

1 : 동차 클래스(CCar) 트럭과 택시를 현

class CCar {

:

색상, 배기량, 현재 , 최 량, 금, 주행거리;

메 드 :

가 하라, 멈춰라, 시동을켜라;

};

문제점 : 실제 객체가 트럭 라

과 주행거리는 필 .

실제 객체가 택시라 최 량 필

8 상 2

1. 상 본 개

2 : 동차(CCar), 트럭(CTruck), 택시(CTaxi) 클래스 만들

class CCar {:색상, 배기량, 현재 ;

메 드:가 하라, 멈춰라, 시동을켜라;

};

class CTruck {:색상, 배기량, 현재 , 최 량;

메 드:가 하라, 멈춰라, 시동을켜라;

};

class CTaxi {:색상, 배기량, 현재 , 금, 주행거리;

메 드:가 하라, 멈춰라, 시동을켜라;

};

문제점 : 코드 복

CTruck CCar 동

CTaxi 역시 CCar 동

à 업 비효

코드 복, 비효 제거하는

à상

8 상 3

1. 상 본 개

상 개

n CTruck과 CTaxi 클래스 시

CCar 상 복

내 다시 언 할 필 가 없

n 상 본 문

class CTruck : public CCar {

:

최 량;

메 드:

};

8 상 4

1. 상 본 개

base 클래스 derived 클래스

n base 클래스 : CCar 클래스

n derived 클래스 : CTruck 클래스, CTaxi 클래스

base derived 클래스 계는 상 적 개

n CCar 클래스를 CVehicle 클래스 상 아 만든다

상 계가 연스럽게 립하는 경

n is-a 계 : 트럭 동차 다. 택시는 동차 다. 사과는 과 다.

n 그 에 존 클래스 든 특 상 고 할

상 : 코드 활 한 강 한 수단

8 상 5

2. 상 문제 제

: 원 나타내는 CCircle 클래스

#define PI 3.14

class CCircle {public :

int x, y; // 심double Radius; // 반 름

public :double GetArea() { return (PI * Radius * Radius); } // 면적

};

int main(void){

CCircle Cir;Cir.x = 1; Cir.y = 1; Cir.Radius = 5;

cout << Cir.GetArea() << endl;

return 0;}

편 상 든 는 public에

8 상 6

2. 상 문제 제

: 를 나타내는 CSphere 클래스

n 심 (x, y, z), 름(Radius), 적 함수, 피 함수à CCircle 상 !

#define PI 3.14

class CCircle {public :

int x, y; // 심double Radius; // 반 름

public :double GetArea() { return (PI * Radius * Radius); } // 면적

};

class CSphere : public CCircle {// CCircle 터 상public :

int z;public :

double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }};

int main(void){

CSphere Sph;Sph.x = 1; Sph.y = 1; Sph.z = 1; Sph.Radius = 5; // Sph:x, y, Radius 상

cout << " 의 면적 : " << Sph.GetArea() << endl; // Sph:GetArea 상cout << " 의 피 : " << Sph.GetVolume() << endl;return 0;

}

프 그램 문제점 ?

8 상 7

2. 상 문제 제

상 문제 제

1. 액 스 정

ØCCircle 수들 private 역에 포함시킨다 à 에러 생

Ø액 스 정 종류 : public, private, protected

2. 생

Ø base 클래스 derived 클래스에 생 가 필 하다 …

Ø , 호출 , 호출 순

3. CCircle과 CSphere 클래스 GetArea 함수

Ø함수 름 능 동 하 현 차 가 남

ü CCircle : pi * r * r;

ü CSphere : 4 * pi * r * r;

Ø함수 라 !

8 상 8

3. base 클래스 접근 제어 protected

액 스 정 치 종류

액 스 정 public과 private에 한 상 한 접근

base

액 스 정

public private

포함 역 내 접근 포함 역 내 접근

public public O private X

private private O private X

8 상 9

3. base 클래스 접근 제어 protected

다 프 그램 문제점 ?

#define PI 3.14

class CCircle {private : // 멤버 변수를 private으 언

int x, y; // 심double Radius; // 반 름

public :double GetArea() { return (PI * Radius * Radius); }

};

class CSphere : public CCircle {private :

int z;

public :double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

int main(void){

return 0;}

public 상

base 클래스 private

접 접근 허 하 않

8 상 10

3. base 클래스 접근 제어 protected

protected

n 접근 허 하 않 à private과 동

n derived 클래스에 접근 허 à public과 동

액 스 정 에 한 상 한 접근

n protected 포함

주 public 상 사 !

base

액 스정

public protected private

포함 역 내 접근 포함 역 내 접근 포함 역 내 접근

public public O protected O private X

protected protected O protected O private X

private private O private O private X

8 상 11

3. base 클래스 접근 제어 protected

: CCircle 수들 protected 포함

#define PI 3.14

class CCircle {protected : // 멤버 변수를 protected 언

int x, y; // 심double Radius; // 반 름

public :double GetArea() { return (PI * Radius * Radius); }

};

class CSphere : public CCircle {private :

int z;

public :double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }};

int main(void){

CCircle Cir;Cir.x = 5;

return 0;}

에러 : x는 protected à 접근 허 않

8 상 12

#define PI 3.14

class CCircle {protected :

int x, y; // 심double Radius; // 반 름

public :double GetArea() { return (PI * Radius * Radius); }

};

class CSphere : public CCircle {private :

int z;

public :CSphere(int a, int b, int c, double r) // 생 자

{ x = a; y = b; z = c; Radius = r; }double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

int main(void){

CSphere Sph(1, 2, 3, 4);cout << Sph.GetVolume() << endl;

return 0;}

4. 상 계에 생

: CSphere 생 추가

생 : base 클래스 protected에 한 접근 가능

à문제 없 수행

à CCircle 클래스에 생 를 추가한다 ???

8 상 13

4. 상 계에 생

derived 클래스 객체 생 시 리 생 순

n base 클래스 생 à derived 클래스 생

derived 클래스 객체 생 시 생 수행 순

n CCircle 클래스 생 수행à CSphere 클래스 생 수행

n 앞 에 CCircle 클래스 생 는? 폴트 생 !

n CCircle 클래스 생 를 시적 호출하는 ???

à 초 화 문

8 상 14

4. 상 계에 생

: base 클래스 생 호출

#define PI 3.14

class CCircle {protected :

int x, y; // 심double Radius; // 반 름

public :CCircle(int a, int b, double r) : x(a), y(b), Radius(r) { }double GetArea() { return (PI * Radius * Radius); }

};

class CSphere : public CCircle {private :

int z;

public :CSphere(int a, int b, int c, double r) : CCircle(a, b, r), z(c) { }double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

int main(void){

CSphere Sph(1, 2, 3, 4);cout << Sph.GetVolume() << endl;

return 0;}

base 클래스 생 호출

8 상 15

4. 상 계에 생

고 사항

n 다 과 같 초 화 문 사 가

ØCSphere(int a, int b, int c, double r) : x(a), y(b), z(c), Radius(r) { }

Ø아 x, y, Radius 수가 생 전 므 초 화 가능

ü base 클래스 수는 드시 해당(base) 클래스 생 초 화

n 앞 에 다 과 같 초 화는 가능할 ?

ØCSphere(int a, int b, int c, double r) { x = a; y = b; z = c; Radius =

r; }

Ø 생 가 수행 전에 CCircle 생 가 수행 어야만

ü 경 폴트 생 (매개 수가 없는 생 )가 수행

à CCircle 클래스에 폴트 생 가 존 하 않 므 수행 가

8 상 16

4. 상 계에 생

상 계에 호출 순 : 생 역순!

#define PI 3.14

class CCircle {protected :

int x, y; // 심double Radius; // 반 름

public :CCircle(int a, int b, double r) : x(a), y(b), Radius(r) {

cout << "CCircle 생 자" << endl; }~CCircle() { cout << "CCircle 멸자" << endl; }double GetArea() { return (PI * Radius * Radius); }

};

class CSphere : public CCircle {private :

int z;

public :CSphere(int a, int b, int c, double r) : CCircle(a, b, r), z(c) {

cout << "CSphere 생 자" << endl; }~CSphere() { cout << "CSphere 멸자" << endl; }double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

int main(void){

CSphere Sph(1, 1, 1, 1);

cout << Sph.GetArea() << endl;cout << Sph.GetVolume() << endl;

return 0;}

CSphere 객체 하나에

한 호출 주

8 상 17

5. 함수 정

앞 에 CSphere 객체 적(GetArea)에 주

n 적 = 4 * PI * r * r = 12.56

n 에 는 원 적 계산 함수 GetArea를 상 아 사 했 문에

à PI * r * r = 3.14가 나

원 적, 적 하는 함수 GetArea 하

GetArea 함수를 호출하는 객체에 라 신 함수가 수행 하

à 함수 정 (function overriding)

int main(void){

CSphere Sph(1, 1, 1, 1);

cout << Sph.GetArea() << endl;cout << Sph.GetVolume() << endl;

return 0;}

8 상 18

// class CCircle 생략

class CSphere : public CCircle {private :

int z;

public :CSphere(int a, int b, int c, double r) : CCircle(a, b, r), z(c) {

cout << "CSphere 생 자" << endl; }~CSphere() { cout << "CSphere 멸자" << endl; }double GetArea() { return (4 * PI * Radius * Radius); } // 함수 재정의double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

int main(void){

CSphere Sph(1, 1, 1, 1);

cout << Sph.GetArea() << endl; // CSphere의 GetArea 함수 호출cout << Sph.GetVolume() << endl;

return 0;}

5. 함수 정

함수 정 를 해 CSphere GetArea 함수 현

CCircle GetArea 함수는 상 는가?

CCircle 객체를 해 만 호출 가능한가?

8 상 19

5. 함수 정

base 클래스(CCircle) GetArea 함수 호출

n CCircle 클래스 GetArea 함수 역시 상

n CSphere 함수에 CCircle GetArea를 호출하는

Ø 다 코드(CSphere 함수 GetArea에 ) 미는?

ü double GetArea() { return (4 * GetArea()); }

ü CSphere 함수 GetArea 호출à 무한 복 호출

Ø CCircle GetArea를 호출하는

ü double GetArea() { return (4 * CCircle::GetArea()); }

ü 정 연산 :: 사

n CSphere 클래스 에 CSphere 객체를 한 함수 호출

Ø CSphere sph;

Ø Sph.CCircle::GetArea(); // CCircle GetArea 함수 호출, :: 사

만약 CShpere 클래스에 int x, y가 언 다

n CCricle x, y 역시 존 함

n CCircle::x, CCircle::y 같 접근 가능

8 상 20

6. 폴트 액 스 정 조체

클래스 조체 차

n public, protected, private 역 없 경 폴트 역

Ø클래스 : private

Ø 조체 : public

n 상 클래스 시 derived 클래스 폴트 액 스 정

Ø derived 클래스가 클래스 경 : private

Ø derived 클래스가 조체 경 : public

Ø base 클래스가 클래스 냐 조체 냐는 무

struct CSphere : CCircle { // derived가 struct이므 폴트 public 상

private :

int z;

public :

CSphere(int a, int b, int c, double r) : CCircle(a, b, r), z(c) { }

double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

다 과 동

struct CSphere : public CCircle

8 상 21

6. 폴트 액 스 정 조체

다 프 그램 문제점 ?#define PI 3.14

class CCircle {protected :

int x, y; // 심double Radius; // 반 름

public :CCircle(int a, int b, double r) : x(a), y(b), Radius(r) { }double GetArea() { return (PI * Radius * Radius); }

};

class CSphere : CCircle {// derived가 class이므 폴트 private 상private :

int z;

public :CSphere(int a, int b, int c, double r) : CCircle(a, b, r), z(c) { }double GetVolume() { return ((4.0/3.0) * PI * Radius * Radius * Radius); }

};

int main(void){

CSphere Sph(1, 1, 1, 1);cout << Sph.GetArea() << endl;cout << Sph.GetVolume() << endl;return 0;

}

8 상 22

7. derived 클래스 상

derived 클래스 상

n 생 호출 순 에 주

class CPoint1 {private :

int x;

protected :int u;

public :CPoint1(int a) : x(a) { cout << "CPoint1 생 자" << endl; }~CPoint1() { cout << "CPoint1 멸자" << endl; }void Print() { cout << "CPoint1" << endl; }

};

class CPoint2 : public CPoint1 {private :

int y;

protected :int v;

public :CPoint2(int a, int b) : CPoint1(a), y(b)

{ cout << "CPoint2 생 자" << endl; }~CPoint2() { cout << "CPoint2 멸자" << endl; }void Print() { cout << "CPoint2" << endl; }

};

8 상 23

7. derived 클래스 상

코드 계

class CPoint3 : public CPoint2 {private :

int z;

protected :int w;

public :CPoint3(int a, int b, int c) : CPoint2(a, b), z(c)

{ cout << "CPoint3 생 자" << endl; }~CPoint3() { cout << "CPoint3 멸자" << endl; }void Print() {

CPoint1::Print(); // CPoint1의 Print 함수 호출CPoint2::Print(); // CPoint2의 Print 함수 호출cout << "CPoint3" << endl;

}};

int main(void){

CPoint3 P3(1, 2, 3);P3.Print();

return 0;}

Print 함수 정

CPoint1, CPoint2 Print 함수

8 상 24

8. 다 상

다 상 : 2개 상 클래스 동시에 상 는 경

class CPointX {protected :

int x;int a;

public :CPointX(int a) : x(a) { cout << "CPointX 생 자" << endl; }~CPointX() { cout << "CPointX 멸자" << endl; }void Print() { cout << "CPointX" << endl; }

};

class CPointY {protected :

int y;int a;

public :CPointY(int b) : y(b) { cout << "CPointY 생 자" << endl; }~CPointY() { cout << "CPointY 멸자" << endl; }void Print() { cout << "CPointY" << endl; }

};

8 상 25

8. 다 상

코드 계

class CPointXYZ : public CPointX, public CPointY { // 다 상private :

int z;

public :CPointXYZ(int a, int b, int c) : CPointX(a), CPointY(b), z(c)

{ cout << "CPointXYZ 생 자" << endl; }~CPointXYZ() { cout << "CPointXYZ 멸자" << endl; }void Print() {

// cout << "a : " << a << endl; // 에러발생, 어 a?CPointX::Print(); // CPointX의 Print 함수 호출CPointY::Print(); // CPointY의 Print 함수 호출cout << "CPointXYZ" << endl;

}};

int main(void){

CPointXYZ Pxyz(1, 2, 3);Pxyz.Print();

return 0;}

생 호출 순 : 어느 쪽 를 ?

쪽(클래스 언 시 시 시 순 )

호 문제 생

CPointX::a, CPointY::a 같 사

8 상 26

9. virtual base 클래스

다 상 고 사항

class CPointX {protected :

int x;

public :CPointX(int a) : x(a) { cout << "CPointX 생 자" << endl; }~CPointX() { cout << "CPointX 멸자" << endl; }void Print() { cout << "CPointX" << endl; }

};

class CPointXY : public CPointX {protected :

int y;

public :CPointXY(int a, int b) : CPointX(a), y(b)

{ cout << "CPointXY 생 자" << endl; }~CPointXY() { cout << "CPointXY 멸자" << endl; }void Print() { cout << "CPointXY" << endl; }

};

class CPointXZ : public CPointX {protected :

int z;

public :CPointXZ(int a, int c) : CPointX(a), z(c)

{ cout << "CPointXZ 생 자" << endl; }~CPointXZ() { cout << "CPointXZ 멸자" << endl; }void Print() { cout << "CPointXZ" << endl; }

};

8 상 27

9. virtual base 클래스

코드 계

class CPointXYZ : public CPointXY, public CPointXZ {private :

int xyz;

public :CPointXYZ(int a, int b, int c) : CPointXY(a, b), CPointXZ(a, c), xyz(0)

{ cout << "CPointXYZ 생 자" << endl; }~CPointXYZ() { cout << "CPointXYZ 멸자" << endl; }void Print() {

// cout << "x : " << x << endl; // 에러발생, 어 x?CPointX::Print(); // VC++ 6.0에 는 에러 발생CPointXY::Print();CPointXZ::Print();cout << "CPointXYZ" << endl;

}};

int main(void){

CPointXYZ Pxyz(1, 2, 3);Pxyz.Print();

return 0;}

호 문제 생

x 2개, y 1개, z 1개 존

CPointX 단 한 만

상 는

à virtual base 클래스 정

class CPointXY : virtual public CPointX { ... }

class CPointXZ : virtual public CPointX { ... }

수정 후 출 결과를 비 해 보라. ( 폴트 생 자 필수)

8 상 28

10. derived 클래스 폴트 복사 생 폴트 연산

폴트 복사 생 폴트 연산 본 동 식

n 단 복사

derived 클래스 폴트 복사 생 폴트 연산

n 단 복사?

n 다 과 같 단 복사를 수행하는 복사 생 문제점 ?

class CPoint {

private :

int x, y;

public :

CPoint(const CPoint &Po) { x = Po.x; y = Po.y; } // 복사 생 자

CPoint &operator=(const CPoint &Po) // 입 연산자

{ x = Po.x; y = Po.y; return (*this); }

};

class CPoint3 : public CPoint {

CPoint3(const CPoint3 &Po) { x = Po.x; y = Po.y; z = Po.z; }

}x 접근 가 : CPoint private !

8 상 29

10. derived 클래스 폴트 복사 생 폴트 연산

derived 클래스 폴트 복사 생 폴트 연산 동

n 단 복사

n base 클래스 복사 생 연산 호출

n 만약, base 클래스 복사 생 연산 를 private 시

적 하고, derived 클래스에 는 시적 하 않는다 ?

Ø base 객체 derived 객체에 한 복사 생 연산 가

class CPoint3 :public CPoint {

private :

int z;

public :

CPoint3(const CPoint3 &Po) : CPoint(Po) { z = Po.z; }

CPoint3 &operator=(const CPoint3 &Po) {

CPoint::operator=(Po); z = Po.z;

return (*this);

}

};

8 상 30

11. private 생 사

다 프 그램 문제점 ?

생 를 private 역에 치시키는 경 ?

class CPoint {private :

int x, y;CPoint(int a, int b) : x(a), y(b) { } // 생 자, private 멤버임

public :void Print() { cout << "(" << x << ", " << y << ")" << endl; }

};

int main(void){

CPoint P1(3, 4);P1.Print();

return 0;}

private 역에 는 생 호출 가à에러 생

8 상 31

11. private 생 사

private 생 사

n 프 그램 전체적 한 객체 생 사

class CPoint {private :

int x, y;CPoint(int a, int b) : x(a), y(b) { }~CPoint() { if (OnlyPoint != NULL) delete OnlyPoint; }static CPoint *OnlyPoint; // 유일한 CPoint 객체를 가리킬 포인터

public :static CPoint *GetPoint() { // OnlyPoint를 반환하는 함수

if (OnlyPoint == NULL) // 최초 수행 시 객체 생OnlyPoint = new CPoint(3, 4);

return OnlyPoint;}void Print() { cout << "(" << x << ", " << y << ")" << endl; }

};

CPoint *CPoint::OnlyPoint = NULL; // 초기화, 아 객체 생 전

int main(void){

CPoint::GetPoint()->Print();return 0;

}

패 : 복적 생하는문제에 한

해 연

: Singleton 패 – 객체가 하나만 존

à C++과는 개 주제