C++ 11주차 상속
상속
상속한 객체 접근
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Shape {
int x, y; //한 점 (x,y)의 좌표값
int type; //0:미지정, 1:원 2:사각형
public:
Shape() { type = 0; }
void set(int x, int y) {
this->x = x;
this->y = y;
};
void showShape() {
cout << "(" << x << "," << y << ")" << endl;
}
};
class Circle : public Shape {
string color;
public:
void setColor(string color) {
this->color = color;
}
void showCircle();
};
void Circle::showCircle() {
cout << color << ":";
showShape(); //Shape의 showShape() 호출
}
int main()
{
Circle a;
a.set(1, 2); //기본 클래스 Shape의 set(int x, int y) 호출
a.showShape(); //기본 클래스 Shape의 showShape() 호출
a.setColor("Red"); //파생 클래스 Circle의 setColor(string color) 호출
a.showCircle(); //파생 클래스의 showCircle();
}
Output
1
2
(1,2)
Red:(1,2)
Circle 클래스는 Shape 클래스를 상속받는다.
파생클래스의 객체인 a에서 set()과 showShape()는 부모 클래스로부터 상속받은 함수를 호출하고,
setColor(string color)과 showCircle()은 파생 클래스에서 구현되었으므로, 파생 클래스 내의 함수를 호출한다.
상속한 객체의 포인터 접근
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class parentClass{
...
};
class childClass : parentClass{
...
};
int main(){
//파생 클래스로부터 객체 생성
childClass child;
//생성된 객체를 이용한 접근
childClass *cp = &child;
}
생성된 객체를 이용한 접근
*cp
파생 클래스의 포인터로 기본/파생 클래스의 멤버를 접근 가능함
업캐스팅
다운캐스팅
상속관계의 접근 지정자
private
선언된 클래스 내부에서만 접근 가능함
파생 클래스에서 직접 접근이 불가능함
public
- 선언된 클래스나 외부의 어떤 클래스에서 모든 외부 함수에 접근 허용
- 파생 클래스에서 기본 클래스의 public 멤버 접근 가능
protected
- 선언된 클래스에서 접근 가능
- 파생된 클래스에서만 접근 허용
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using namespace std;
#include <string>
#include <iostream>
class Shape {
protected:
int x, y; //한점 (x,y) 좌표값
public:
void set(int x, int y);
void showShape();
};
void Shape::set(int x, int y) { this->x = x; this->y = y; }
void Shape::showShape() { cout << "(" << x << "," << y << ")" << endl; }
class Circle : public Shape {
string color;
public:
void setColor(string color);
void showCircle();
bool equals(Circle p);
};
void Circle::setColor(string color) { this->color = color; }
void Circle::showCircle() {
cout << color << ':';
showShape(); //Shape 클래스의 showShape() 호출
}
bool Circle::equals(Circle p) {
if (x == p.x && p.y && color == p.color)
return true; //정상
else
return false;
}
int main()
{
Shape p;
p.set(2, 3); //정상
p.x - 5; //오류
p.y = 5; //오류
p.showShape();
Circle cp;
cp.set(3, 4);
cp.x = 10; //오류
cp.y - 10; //오류
cp.setColor("Red");
cp.showCircle();
Circle cp2;
cp2.set(3, 4);
cp2.setColor("Red");
cout << ((cp.equals(cp2)) ? "true" : "false");
}
1
2
3
4
5
Output:
(2,3)
Red:(3,4)
true
생성자와 소멸자의 호출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Parent_Constructor {
public:
Parent_Constructor() {
cout << "부모 클래스에서 생성자가 호출 되었습니다." << endl;
}
~Parent_Constructor() {
cout << "부모 클래스에서 소멸자가 호출 되었습니다." << endl;
}
};
class Child_Constructor : public Parent_Constructor {
public:
Child_Constructor() {
cout << "자식 클래스에서 생성자가 호출 되었습니다." << endl;
}
~Child_Constructor() {
cout << "자식 클래스에서 소멸자가 호출 되었습니다." << endl;
}
};
int main(){
Child_Constructor cc;
}
Output
1
2
3
4
부모 클래스에서 생성자가 호출 되었습니다.
자식 클래스에서 생성자가 호출 되었습니다.
자식 클래스에서 소멸자가 호출 되었습니다.
부모 클래스에서 소멸자가 호출 되었습니다.
- 위에서 설명한 것과 같이, 부모 클래스와 자식 클래스 모두 생성자를 가지고 있을때 부모 클래스 - 자식 클래스 순으로 생성자가 실행됨
- 부모 클래스와 자식 클래스가 모두 소멸자를 가지고 있을때는, 반대로 자식 클래스 - 부모 클래스 순으로 소멸자가 실행됨
생성자 매개 변수 전달
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class TV {
int size; //스크린 크기
public:
TV() { size = 20; }
TV(int size) { this->size = size; }
int getSize() { return size; }
};
class WideTV : public TV { //TV 상속받는 WideTV
bool videoIn;
public:
WideTV(int size, bool videoIn) : TV(size) { this->videoIn = videoIn; }
bool getVideoIn() { return videoIn; }
};
class SmartTV : public WideTV { //WideTV 상속받는 SmartTV
string ipAddr; //인터넷 주소
public:
SmartTV(string ipAddr, int size) : WideTV(size, true) { this->ipAddr = ipAddr; }
string getIpAddr() { return ipAddr; }
};
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;
}
1
2
3
4
5
Output:
size = 32
videoIn = true
IP = 192.0.0.1
htv
1 2 3 4
- TV 영역 : int size = 32; - WideTV 영역: bool videoIn - SmartTV 영역: string ipAddr = "192.0.0.1"
상속 지정
다중 상속
- 여러 클래스를 동시에 상속 받는 것
예시)
1
class multimediaPlayer : public mp3Player, public videoPlayer
예시 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//다중 상속
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 { public: 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;
}
1
2
3
4
Output:
2 + 4 = 6
100 - 8 = 92
다중 상속의 문제
예시)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
class Animal{ public: int lifetime; }; class eagle : public Animal{ public: int wing; }; class lion : public Animal{ public: int tooth; }; class kimera : public eagle, public lion{ public: int leg; }; int main(){ kimera wild; wild.wing = 10; wild.tooth = 20; wild.lifetime = 30; }
1 2
심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태 오류(활성) E0266 "kimera::lifetime"이(가) 모호합니다. 11th F:\School\23-2\Cpp\Cpp_Study\11th\11th.cpp 137
Virtual 이용한 다중 상속의 문제 해결
- 가상 상속을 통하여, 기본 크랠스의 멤버를 한번만 생성하도록 설정이 가능함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Animal {
public:
int lifetime;
};
class eagle : virtual public Animal {
public:
int wing;
};
class lion : virtual public Animal{
public:
int tooth;
};
class kimera : public eagle, public lion {
public:
int leg;
};
int main(){
kimera wild;
wild.wing = 10;
wild.tooth = 20;
wild.lifetime = 30;
}
파생 클래스의 함수 재정의
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Base {
public:
void f() { cout << "Base::f() called" << endl; }
};
class Derived : public Base {
public:
void f() { cout << "Derived::f() called" << endl; }
};
int main(){
Derived d, * pDer;
pDer = &d;
pDer->f(); //Derived::f() 호출
Base* pBase;
pBase = pDer; //업캐스팅
pBase->f(); //Base::f() 호출
}
Output
1
2
Derived::f() called
Base::f() called
가상함수와 오버라이딩
가상 함수
- Virtual로 선언
- 함수에 대한 호출 바인딩을 실행 시간에 결정(동적 바인딩)
- 오버라이딩
- 파생 클래스에서 기본 클래스의 함수와 동일한 이름의 함수 선언
- 기본 클래스의 함수 내용을 재정의
- 다형성을 위한 기능
- 가상함수에 대한 오버라이딩을 할 경우 동적 바인딩이 가능함
- 파생 클래스에서 기본 클래스의 함수와 동일한 이름의 함수 선언
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Base2 {
public:
virtual void f() { //가상 함수
cout << "Base::f() Called" << endl;
}
};
class Derived2 : public Base2 {
public:
virtual void f() { //오버라이딩
cout << "Derived::f() called" << endl;
}
};
int main(){
Derived2 d, * pDer2;
pDer2 = &d;
pDer2->f(); //Derived::f() 호출
Base2* pBase2;
pBase2 = pDer2; //업캐스팅
pBase2->f(); //Base::f() 호출
}
Output
1
2
Derived::f() called
Derived::f() called
예시
class Base2 {
public:
virtual void f() {
cout << "Base::f() Called" << endl;
}
};
class Derived2 : public Base2 {
public:
virtual void f() {
cout << "Derived::f() called" << endl;
}
};
int main(){
Derived2 d, * pder; //Base 멤버의 void f()는 호출되지 않음
pder = &d;
pder->f(); //derived::f() 호출
Base2* pbase;
pbase = pder; //업 캐스팅
pbase->f(); // 동적 바인딩 발생 derived::f() 실행
}
Output
1
2
Derived::f() called
Derived::f() called
오버라이딩의 목적
- 기본 클래스에서는 인터페이스 생성
- 파생클래스에서는 실제 동작 정의(다형성 구현)
- 예시 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Shape {
public:
//가상 함수 선언(파생클래스에서 구현할 인터페이스 역활)
virtual void draw() {}
};
class Circle : public Shape {
public:
virtual void draw() //하위 클래스에서 다형성 구현
{
cout << "Circle을 그리기" << endl;
}
};
class Rect : public Shape {
public:
virtual void draw()
{
cout << "Rect를 그리기" << endl;
}
};
class Line : public Shape {
public:
virtual void draw()
{
cout << "Line을 그리기" << endl;
}
};
void paint(Shape3* p) {
p->draw(); //p가 가르키는 객체에 오버라이딩된 draw() 호출
}
int main(){
paint(new Circle3());
paint(new Rect3());
paint(new Line3());
}
Output
1
2
3
Circle을 그리기
Rect를 그리기
Line을 그리기
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.



