티스토리 뷰
공부/Effective C++
항목 32 ] public 상속 모형은 반드시 "is-a(...는 ...의 일종이다)"를 따르도록 만들자.
-=HaeJuK=- 2010. 3. 8. 10:24728x90
상속 모형은 반드시 "is-a"
• 클래스 D(Derived)를 클래스 B(Base)로부터 public 상속을 통해 파생시켰다
• D 타입으로 만들어진 모든 객체는 또한 B 타입의 객체이지만, 그 반대는 되지 않음
• B 타입의 객체가 쓰일 수 있는 곳에는 D 타입의 객체도 마찬가지로 쓰일 수 있다고 단정
• D 타입이 필요한 부분에 B 타입의 객체를 쓰는 것은 불가능
• 모든 D는 B의 일종이지만, B는 D의 일종이 아님
• C++는 public 상속을 이렇게 해석하도록 문법적으로 지원
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Person {...};
class Student: public Person {...};
// 모든 학생은 사람이지만 모든 사람이 학생은 아님
void eat(const Person& p); // 먹는 것은 누구든 함
void study(const Student& s); // 학과 공부는 학생만 함
void main()
{
Person p; // p는 Person의 일종(사람도 사람이니까)
Student s; // s는 Student의 일종(학생도 학생이니까)
eat(p); // 문제없음. p는 Person.
eat(s); // 문제없음. s는 Student이고, Student는 Person의 일종
study(s); // 좋음
study(p); // 에러, p는 Student가 아님
}
|
cs |
public 상속과 is-a 관계가 똑같은 뜻이라는 직관 때문에 잘못 판단하는 경우가 있음
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
//-----------------------------------------------------------------------------------------
//펭귄은 새의 일종, 새는 날 수 있음
class Bird
{
public:
virtual void fly(); // 새는 날 수 있음
};
class Penguin: public Bird // 펭귄은 새임
{
//...
};
//위의 클래스 상으로는 펭귄은 날 수 있음
//-----------------------------------------------------------------------------------------
//날지 않는 새 종류도 있다는 점을 추가
class Bird {...};
class FlyingBird: public Bird
{
public:
virtual void fly();
};
class Penguin: public Bird
{
//...
};
//-----------------------------------------------------------------------------------------
//다른 방법
//펭귄의 fly 함수를 재정의해서 런타임 에러를 내도록 하는 것
void error(const std::string& msg); // 어딘가에 정의되어 있을 것임
class Penguin: public Brid
{
public:
virtual void fly()
{
error("Attempt to make a penguin fly!");
}
}
//위 경우는 펭귄은 날 수 없다가 아닌 펭귄은 날 수 있지만 날려고 하면 에러가 난다임
//"펭귄은 날 수 없다 - 도장 꽝" 제약사항 추가
class Bird
{
// fly 함수가 선언되지 않았음
};
class Penguin: public Bird
{
// fly 함수가 선언되지 않았음
};
void main()
{
Penguin p;
p.fly(); // error
}
//-----------------------------------------------------------------------------------------
//Sqare(정사각형) 클래스는 Rectangle(직사각형) 클래스로부터 상속을 받아야 하는가?
//학교에서만 맞는 말임
class Rectangle
{
public:
virtual void setHeight(int newHeight);
virtual void setWidth(int newWidth);
virtual int height() const; // 현재의 값을 반환
virtual int width() const;
};
void makeBigger(Rectangle& r) // r의 넓이를 늘리는 함수
{
int oldHeight = r.height();
r.setWidth(r.width()+10); // r의 가로 길이에 10을 더함
assert(r.height() == oldHeight); // r의 세로 길이가 변하지 않는다는 조건에 단정문을 걸어둠
}
//-----------------------------------------------------------------------------------------
//public 상속을 써서 정사각형을 직사각형처럼 처리하게 허용하는 코드
class Square: public Rectangle
{
//...
};
void main()
{
Square s;
assert(s.width() == s.height()); // 이 단정문은 모든 정사각형에 대해서 참이어야 함
makeBigger(s); // 상속된 것이므로 s는 Rectangle의 일종임, s의 넓이를 늘릴 수 있음
assert(s.width() == s.hegith()); // 이 단정문이 모든 정사각형에 대해 참이어야 함
}
//-----------------------------------------------------------------------------------------
// 문제 발생
• makeBigger 함수를 호출하기 전에, s의 세로 길이와 가로 길이는 동일해야함
• makeBigger 함수가 실행되는 중에, s의 가로 길이는 변하는데 세로 길이는 안변해야 함
• makeBigger 함수가 복귀한 후에, s의 세로 길이와 가로 길이는 동일해야 함
• 결국 상속 받도록 만들면 안됨
• is-a 관계가 아닌 것들을 is-a 관계로 모형화 하면 설계가 이상하게 꼬임
|
cs |
총평
기본 클래스 적용되는 모든 것은 파생 클래스에 공통적이어야 합니다.
파생 클래스는 기본 클래스 객체의 일종이기 때문입니다.
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- script
- 서귀포블루버블
- C#.NET
- Windows
- 스쿠버다이빙
- 패턴
- 서귀포
- C++
- Effective c++
- 제주도
- Build
- C# 고급 기술
- DLL
- PowerShell
- 블루버블다이브팀
- 성산블루버블
- OpenSource
- Linux
- 현포다이브
- 울릉도
- effective
- C#
- 스쿠버 다이빙
- 블루버블다이빙팀
- 네트워크 정보
- CMake
- C
- 암호화
- 외돌개
- 블루버블
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함
250x250