Post

🐒 chap9. 좔상화와 C++의 OPP

⭐ 9.1 좔상화

  • OOPμ—μ„œμ˜ 좔상화 : 좔상 μžλ£Œν˜•μ„ λ‹€λ£¨λŠ” 것, 클래슀 기반의 객체지ν–₯μ—μ„œ 좔상 μžλ£Œν˜•μ€ 좔상 클래슀λ₯Ό λ‹€λ£¨λŠ” κ²ƒμž…λ‹ˆλ‹€.
  • 좔상 클래슀 : 객체λ₯Ό μƒμ„±ν•˜κ³  λ‚˜μ„œ, μ‚¬μš©ν•˜κΈ°μ—λŠ” 아직 μ€€λΉ„λ˜μ§€λ„ μ™„λ£Œλ˜μ§€λ„ μ•Šμ€ μƒνƒœ.
  • λ¬Έμž₯의 λͺ…사가 클래슀라고 보고, 클래슀 κ°„μ—λŠ” λ‹€μŒκ³Ό 같은 관계가 성립할 수 μžˆμŠ΅λ‹ˆλ‹€.

    • 인간은 사과λ₯Ό λ¨ΉλŠ”λ‹€.
    • 인간은 μ˜€λ Œμ§€λ₯Ό λ¨ΉλŠ”λ‹€.
    • 인간은 과일을 λ¨ΉλŠ”λ‹€.
    • μ΄λ•Œ 과일은 사과와 μ˜€λ Œμ§€λ₯Ό ν¬ν•¨ν•˜λŠ” λΆ€λͺ¨ 좔상 ν΄λž˜μŠ€μž…λ‹ˆλ‹€. 그리고 사과와 μ˜€λ Œμ§€λŠ” ꡬ상 μžλ£Œν˜•μ΄λΌκ³  ν•©λ‹ˆλ‹€.
    • 과일을 더 μΆ”μƒμ μœΌλ‘œ λ§Œλ“€μ–΄ 인간은 μ†Œν™” κ°€λŠ₯ ν•œ 것을 λ¨ΉλŠ”λ‹€.
    • μ†Œν™” κ°€λŠ₯ν•œ 것은 과일보닀 λΆ€λͺ¨ 좔상 ν΄λž˜μŠ€μž…λ‹ˆλ‹€.
  • κ³Όλ„ν•œ 좔상화 : ν•„μš”ν•œ μˆ˜μ€€λ³΄λ‹€ 더 좔상적인 좔상 μžλ£Œν˜•, ν•„μš”ν•œ 사항보닀 더 좔상 μžλ£Œν˜•μ„ μƒμ„±ν•˜λŠ” 것.
  • 좔상화 원칙 : ν”„λ‘œκ·Έλž¨μ˜ μ€‘μš”ν•œ 각 κΈ°λŠ₯은 μ†ŒμŠ€ μ½”λ“œμ˜ 였직 ν•œ λΆ€λΆ„μ—μ„œλ§Œ κ΅¬ν˜„λ˜μ–΄μ•Ό ν•œλ‹€. λΉ„μŠ·ν•œ κΈ°λŠ₯을 λ³„κ°œμ˜ μ½”λ“œμ—μ„œ μˆ˜ν–‰ν•  λ•ŒλŠ” 일반적으둜 λ‹€μ–‘ν•œ 뢀뢄을 좔상화해 ν•˜λ‚˜λ‘œ κ²°ν•©ν•˜λŠ” 편이 μ’‹λ‹€.
  • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ 상속과 λ‹€ν˜•μ„±μ€ 좔상화λ₯Ό μœ„ν•΄ ν•„μš”ν•©λ‹ˆλ‹€.

  • 상속은 μ†Œν™”κ°€λŠ₯ν•œ 것과 같은 좔상 ν΄λž˜μŠ€λŠ” 사과 λ“±μ˜ μ†Œν™” κ°€λŠ₯ν•œ 것 κ΄€λ ¨ ꡬ상 ν΄λž˜μŠ€μ— λŒ€ν•œ λΆ€λͺ¨νƒ€μž…이며 상속에 μ˜ν•΄ 이루어 μ§‘λ‹ˆλ‹€.

  • λ‹€ν˜•μ„± μ—­μ‹œ μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. 좔상 μžλ£Œν˜•μ—λŠ” ν•΄λ‹Ή 좔상화 μˆ˜μ€€μ—μ„œ κΈ°λ³Έ κ΅¬ν˜„μ„ 갖지 λͺ»ν•˜λŠ” ν–‰μœ„κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ˜ˆμ‹œλ‘œ 먹을 수 μžˆλŠ”κ²ƒ(Eatable) ν΄λž˜μŠ€μ—μ„œ eatable_get_taste와 같은 ν–‰μœ„ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ κ΅¬ν˜„λœ μ†μ„±μœΌλ‘œμ„œμ˜ 맛은 (taste)은 먹을 수 μžˆλŠ” 것 (Eatable) 객체λ₯Ό λ‹€λ£° λ•Œ μ •ν™•ν•œ 값을 κ°€μ§ˆ 수 μ—†μŠ΅λ‹ˆλ‹€. β†’ 먹을 수 μžˆλŠ” κ²ƒμ—λŠ” 맛에 λŒ€ν•œ 속성을 μ •μ˜ ν•  수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€ν˜•μ„±μœΌλ‘œμ„œ ν’€μ–΄λ‚Έλ‹€.

  • μžμ‹ ν΄λž˜μŠ€κ°€ μΆ©λΆ„νžˆ ꡬ체적일 λ•Œλ§Œ μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 사과 κ°μ²΄λŠ” 맛에 λŒ€ν•΄ 단맛을 λ°˜ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€ν˜•μ„±μ€ λ°”λ‘œ 이 지점 μ—μ„œ 도움이 λ©λ‹ˆλ‹€.

  • μžμ‹ ν΄λž˜μŠ€κ°€ μ˜€λ²„λΌμ΄λ”©ν•  수 μžˆλŠ” ν–‰μœ„ ν•¨μˆ˜λ₯Ό 가상 ν•¨μˆ˜λΌκ³  λΆˆλ €μŠ΅λ‹ˆλ‹€. 가상 ν•¨μˆ˜λŠ” μ •μ˜κ°€ μ•„μ˜ˆ 없을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 가상 ν•¨μˆ˜λŠ” μ†Œμœ μž 클래슀λ₯Ό 좔상화 ν•©λ‹ˆλ‹€.

  • νŠΉμ • μˆ˜μ€€μ—μ„œ λ”μš± μΆ”μƒν™”ν•΄μ„œ, 속성과 κΈ°λ³Έ μ •μ˜λ₯Ό 갖지 μ•ŠλŠ” 가상 ν•¨μˆ˜λ§Œμ„ ν¬ν•¨ν•˜λŠ” ν΄λž˜μŠ€κΉŒμ§€ λ„λ‹¬ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 클래슀λ₯Ό μΈν„°νŽ˜μ΄μŠ€λΌκ³  ν•©λ‹ˆλ‹€. 즉 μΈν„°νŽ˜μ΄μŠ€λŠ” κΈ°λŠ₯은 λ…ΈμΆœν•˜μ§€λ§Œ κ΅¬ν˜„μ€ μ „ν˜€ λ…ΈμΆœν•˜μ§€ μ•ŠμœΌλ©°, 일반적으둜 μ†Œν”„νŠΈμ›¨μ–΄ ν”„λ‘œμ νŠΈμ—μ„œ λ‹€μ–‘ν•œ μ»΄ν¬λ„ŒνŠΈ μ‚¬μ΄μ˜ μ˜μ‘΄μ„±μ„ λ§Œλ“œλŠ”λ° μ‚¬μš©ν•©λ‹ˆλ‹€. μ˜ˆμ‹œλ‘œ λ¨ΉλŠ” 자(Eater)와 먹을 수 μžˆλŠ” 것(Eatable)ν΄λž˜μŠ€κ°€ μΈν„°νŽ˜μ΄μŠ€μž…λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef enum {SWEET, SOUR} taste_t;

//ν•¨μˆ˜ 포인터 μžλ£Œν˜•
typedef taste_t (*get_taste_func_t)(void*);

typedef struct {
	// 가상 ν•¨μˆ˜μ— λŒ€ν•œ μ •μ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터
	get_taste_func_t get_taste_func;
} eatable_t;

eatable_t* eatable_new() {...} // ν• λ‹Ήμž ν•¨μˆ˜
void eatable_ctor(eatable_t* eatable){
	// 가상 ν•¨μˆ˜μ— λŒ€ν•œ κΈ°λ³Έ μ •μ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€.
	eatable->get_taste_func = NULL;
}

// 가상 ν–‰μœ„ ν•¨μˆ˜
taste_t eatable_get_taste(eatable_t* eatable){
	return eatable->get_taste_func(eatable);
}
  • μΈν„°νŽ˜μ΄μŠ€μ— λŒ€ν•œ μ •μ˜μ™€ 섀계 κ΄€μ μ—μ„œ 이해할 수 μžˆλŠ” 이유 μ™Έμ—λŠ” 기본적으둜 먹을 수 μžˆλŠ” 것(Eatable) μΈν„°νŽ˜μ΄μŠ€μ—μ„œ 객체λ₯Ό μƒμ„±ν•΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€. 먹을 수 μžˆλŠ” 것(Eatable) μΈν„°νŽ˜μ΄μŠ€μ—μ„œ 객체λ₯Ό μƒμ„±ν•˜λŠ” 것이 C의 κ΄€μ μ—μ„œ κ°€λŠ₯ν•˜μ§€λ§Œ 좩돌이 λ°œμƒν•©λ‹ˆλ‹€. μ ˆλŒ€ ν•΄μ„œλŠ” μ•ˆλ©λ‹ˆλ‹€.
1
2
3
4
5
6
eatable_t *eatable = eatable_new();
eatable_ctor(eatable);
taste_t taste = eatable_get_taste(eatable); // μ„Έκ·Έλ©˜ν…Œμ΄μ…˜ 였λ₯˜
taste_t taste = eatable_get_taste((eatable_t)orange); //

free(eatable);
  • 좔상 μžλ£Œν˜•μœΌλ‘œ 객체λ₯Ό μƒμ„±ν•˜μ§€ μ•ŠμœΌλ €λ©΄ 클래슀의 곡용 μΈν„°νŽ˜μ΄μŠ€μ—μ„œ ν• λ‹Ήμž ν•¨μˆ˜λ₯Ό μ œκ±°ν•©λ‹ˆλ‹€. 8μž₯의 접근법을 κΈ°μ–΅ν•œλ‹€λ©΄, ν• λ‹Ήμž ν•¨μˆ˜λ₯Ό μ œκ±°ν•¨μœΌλ‘œμ¨ 였직 μžμ‹ 클래슀만이 λΆ€λͺ¨μ˜ 속성 κ΅¬μ‘°μ²΄λ‘œλΆ€ν„° 객체λ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

  • μ™ΈλΆ€ μ½”λ“œκ°€ 더 이상 λΆ€λͺ¨μ˜ 속성 κ΅¬μ‘°μ²΄λ‘œλΆ€ν„° 객체λ₯Ό 생성할 수 μ—†μŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, eatable_tλ‘œλΆ€ν„° 객체λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν•˜κ²Œ ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 속성 ꡬ쑰체λ₯Ό μ„ μ–Έ μ•žμ— 두어 λΆˆμ™„μ „ μžλ£Œν˜•μœΌλ‘œ λ§Œλ“€κ³ , 곡용 λ©”λͺ¨λ¦¬ ν• λ‹ΉμžμΈ eatable_newλ₯Ό ν΄λž˜μŠ€μ—μ„œ μ œκ±°ν•΄μ•Ό ν•©λ‹ˆλ‹€.

  • 맀우 높은 좔상화 μˆ˜μ€€μ—μ„œλŠ” λͺ¨λ“  ν•¨μˆ˜ 포인터가 NULL인 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°–μŠ΅λ‹ˆλ‹€. 좔상 μžλ£Œν˜•μœΌλ‘œλΆ€ν„° μ™ΈλΆ€ μ½”λ“œκ°€ 객체λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν•˜κ²Œ ν•˜λ €λ©΄ 곡용 μΈν„°νŽ˜μ΄μŠ€μ—μ„œ ν• λ‹Ήμž ν•¨μˆ˜λ₯Ό μ œκ±°ν•΄μ•Ό ν•©λ‹ˆλ‹€.

⭐ 9.2 C++의 객체지ν–₯ ꡬ성물

β˜‘οΈ 9.2.1 μΊ‘μŠν™”

  • OPP 기법을 μ‚¬μš©ν•œ C와 OPPκ°œλ…μœΌλ‘œ κ΅¬ν˜„ν•œ C++ 두 ν”„λ‘œκ·Έλž¨μ— λŒ€ν•΄ μƒμ„±λœ μ–΄μ…ˆλΈ”λ¦¬ λͺ…λ Ήμ–΄λ₯Ό λΉ„κ΅ν•˜κ² μŠ΅λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

typedef struct {
	int width;
	int length;
} rect_t;

int rect_area(rect_t* rect) {
	return rect->width * rect->length;
}

int main(int argc, char**argv){
	rect_t r;
	r.width = 10;
	r.length = 25;
	int area = rect_area(&r);
	printf("Area: %d\n", area);
	return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

class Rect{
public:
	int Area() {
		return width * length;
	}
	int width;
	int length;
};

int main(int argc, char** argv){
	Rect r;
	r.width = 10;
	r.length = 25;
	int area = r.Area();
	std::cout << "Area: " << area << std::endl;
	return 0;
}
1
2
gcc -S ExtremeC_examples_chapter9_1.c -o ex9_1_c.s
g++ -S ExtremeC_exampes_chapter9_1.cpp -o ex9_1_cpp.s
  • C와 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
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
ubuntu@DESKTOP-FFH31MN:~/Extreme-C/ch09-abstraction-and-oop-in-c++$ cat ex9_1_c.s
        .file   "ExtremeC_examples_chapter9_1.c"
        .text
        .globl  rect_area
        .type   rect_area, @function
rect_area:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movq    %rdi, -8(%rbp)
        movq    -8(%rbp), %rax
        movl    (%rax), %edx
        movq    -8(%rbp), %rax
        movl    4(%rax), %eax
        imull   %edx, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   rect_area, .-rect_area
        .section        .rodata
.LC0:
        .string "Area: %d\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $48, %rsp
        movl    %edi, -36(%rbp)
        movq    %rsi, -48(%rbp)
        movq    %fs:40, %rax
        movq    %rax, -8(%rbp)
        xorl    %eax, %eax
        movl    $10, -16(%rbp)
        movl    $25, -12(%rbp)
        leaq    -16(%rbp), %rax
        movq    %rax, %rdi
        call    rect_area
        movl    %eax, -20(%rbp)
        movl    -20(%rbp), %eax
        movl    %eax, %esi
        leaq    .LC0(%rip), %rax
        movq    %rax, %rdi
        movl    $0, %eax
        call    printf@PLT
        movl    $0, %eax
        movq    -8(%rbp), %rdx
        subq    %fs:40, %rdx
        je      .L5
        call    __stack_chk_fail@PLT
.L5:
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long   1f - 0f
        .long   4f - 1f
        .long   5
0:
        .string "GNU"
1:
        .align 8
        .long   0xc0000002
        .long   3f - 2f
2:
        .long   0x3
3:
        .align 8
4:

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
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
ubuntu@DESKTOP-FFH31MN:~/Extreme-C/ch09-abstraction-and-oop-in-c++$ cat ex9_1_cpp.s
        .file   "ExtremeC_examples_chapter9_1.cpp"
        .text
        .local  _ZStL8__ioinit
        .comm   _ZStL8__ioinit,1,1
        .section        .text._ZN4Rect4AreaEv,"axG",@progbits,_ZN4Rect4AreaEv,comdat
        .align 2
        .weak   _ZN4Rect4AreaEv
        .type   _ZN4Rect4AreaEv, @function
_ZN4Rect4AreaEv:
.LFB1731:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movq    %rdi, -8(%rbp)
        movq    -8(%rbp), %rax
        movl    (%rax), %edx
        movq    -8(%rbp), %rax
        movl    4(%rax), %eax
        imull   %edx, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1731:
        .size   _ZN4Rect4AreaEv, .-_ZN4Rect4AreaEv
        .section        .rodata
.LC0:
        .string "Area: "
        .text
        .globl  main
        .type   main, @function
main:
.LFB1732:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $48, %rsp
        movl    %edi, -36(%rbp)
        movq    %rsi, -48(%rbp)
        movq    %fs:40, %rax
        movq    %rax, -8(%rbp)
        xorl    %eax, %eax
        movl    $10, -16(%rbp)
        movl    $25, -12(%rbp)
        leaq    -16(%rbp), %rax
        movq    %rax, %rdi
        call    _ZN4Rect4AreaEv
        movl    %eax, -20(%rbp)
        leaq    .LC0(%rip), %rax
        movq    %rax, %rsi
        leaq    _ZSt4cout(%rip), %rax
        movq    %rax, %rdi
        call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
        movq    %rax, %rdx
        movl    -20(%rbp), %eax
        movl    %eax, %esi
        movq    %rdx, %rdi
        call    _ZNSolsEi@PLT
        movq    _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rdx
        movq    %rdx, %rsi
        movq    %rax, %rdi
        call    _ZNSolsEPFRSoS_E@PLT
        movl    $0, %eax
        movq    -8(%rbp), %rdx
        subq    %fs:40, %rdx
        je      .L5
        call    __stack_chk_fail@PLT
.L5:
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1732:
        .size   main, .-main
        .type   _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB2235:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        cmpl    $1, -4(%rbp)
        jne     .L8
        cmpl    $65535, -8(%rbp)
        jne     .L8
        leaq    _ZStL8__ioinit(%rip), %rax
        movq    %rax, %rdi
        call    _ZNSt8ios_base4InitC1Ev@PLT
        leaq    __dso_handle(%rip), %rax
        movq    %rax, %rdx
        leaq    _ZStL8__ioinit(%rip), %rax
        movq    %rax, %rsi
        movq    _ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rax
        movq    %rax, %rdi
        call    __cxa_atexit@PLT
.L8:
        nop
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE2235:
        .size   _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
        .type   _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB2236:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $65535, %esi
        movl    $1, %edi
        call    _Z41__static_initialization_and_destruction_0ii
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE2236:
        .size   _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
        .section        .init_array,"aw"
        .align 8
        .quad   _GLOBAL__sub_I_main
        .hidden __dso_handle
        .ident  "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long   1f - 0f
        .long   4f - 1f
        .long   5
0:
        .string "GNU"
1:
        .align 8
        .long   0xc0000002
        .long   3f - 2f
2:
        .long   0x3
3:
        .align 8

β˜‘οΈ 9.2.2 상속

  • 상속
    • 첫 번째 접근법
      • μžμ‹ 클래슀의 ν¬μΈν„°λŠ” λΆ€λͺ¨ 클래슀의 ν¬μΈν„°λ‘œ ν• λ‹Ήν•  수 있음
      • μžμ‹ ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ 클래슀의 λΉ„κ³΅κ°œ μ •μ˜μ— μ ‘κ·Όν•  수 있음
      • μžμ‹μ˜ 속성 ꡬ쑰체 μ•ˆμ— ꡬ쑰체 λ³€μˆ˜λ₯Ό λ‘”λ‹€ β‡’ 단일 상속
    • 두 번째 접근법
      • λΆ€λͺ¨μ˜ 속성 ꡬ쑰체의 λΆˆμ™„μ „ μžλ£Œν˜•μœΌλ‘œλΆ€ν„° ꡬ쑰체 포인터λ₯Ό λ‘ 
      • λΆ€λͺ¨ 클래슀의 λΉ„κ³΅κ°œ κ΅¬ν˜„μ— μ˜μ‘΄ν•˜μ§€ μ•ŠμŒ β‡’ 닀쀑 상속 (C++ κ°€λŠ₯)
  • C κ³Ό C++ λ²„μ „μ˜ 상속 차이점

    • C μ–Έμ–΄
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    // File name: ExtremeC_examples_chapter9_2.c
    // Description: Inheritance in C
    
    #include <string.h>
    
    typedef struct {
      char c;
      char d;
    } a_t;
    
    typedef struct {
      a_t parent;
      char str[5];
    } b_t;
    
    int main(int argc, char** argv) {
      b_t b;
      b.parent.c = 'A';
      b.parent.d = 'B';
      strcpy(b.str, "1234");
      // We need to set a break point at this line.
      return 0;
    }
    
    • 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
    
    // File name: ExtremeC_examples_chapter9_2.cpp
    // Description: Inheritance in C++
    
    #include <string.h>
    
    class A {
    public:
      char c; // A
      char d; // B
    };
    
    class B : public A {
    public:
      char str[5];
    };   // 1234
    
    int main(int argc, char** argv) {
      B b;
      b.c = 'A';
      b.d = 'B';
      strcpy(b.str, "1234");
      // We need to set a break point at this line.
      return 0;
    }
    
    1
    2
    
    gcc -g ExtremeC_examples_chapter9_2.c -o ex9_2_c.out
    gdb ./ex9_2_c.out
    
    1
    2
    
    g++ -g ExtremeC_examples_chapter9_2.cpp -o ex9_2_cpp.out
    gdb ./ex9_2_cpp.out
    
    • C++ μ—μ„œ ν–‰μœ„ ν•¨μˆ˜μ™€ 속성을 클래슀 μ•ˆμ— ν•¨κ»˜ λ‘μ—ˆλ‹€κ³  ν—·κ°ˆλ¦¬λ©΄ μ•ˆλ¨ (근데 이 μ˜ˆμ œμ—λŠ” ν–‰μœ„ ν•¨μˆ˜κ°€ μ—†λ‹€κ³  ν–ˆμŒ..)
      • ν–‰μœ„ ν•¨μˆ˜μ™€ 속성은 ν΄λž˜μŠ€μ—μ„œ λ³„κ°œλ‘œ 취급됨
      • 클래슀 λ‚΄μ˜ μœ„μΉ˜μ™€ 상관없이 속성은 μ–Έμ œλ‚˜ νŠΉμ • 객체에 λŒ€ν•΄ 같은 λ©”λͺ¨λ¦¬ 블둝 μ•ˆμ—μ„œ μˆ˜μ§‘λ¨
      • ν•¨μˆ˜λŠ” μ†μ„±κ³ΌλŠ” μ–Έμ œλ‚˜ λ…λ¦½μ μœΌλ‘œ μ‘΄μž¬ν•¨ β‡’ 암묡적 μΊ‘μŠν™”
  • Cμ—μ„œ 상속을 κ΅¬ν˜„ν•˜λŠ” 첫 번째 μ ‘κ·Όλ²•μ—μ„œ 닀쀑 상속이 λ˜μ§€ μ•ŠλŠ” 이유

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    typedef struct {...} a_t;
    typedef struct {...} b_t;
    
    typedef struct {
    	a_t a;
    	b_t b;
    	...
    } c_t;
    
    c_t c_obj;
    a_t* a_ptr = (a_t*)&c_obj;
    b_t* b_ptr = (b_t*)&c_obj;
    c_t* c_ptr = &c_obj;
    
    • c_t ν΄λž˜μŠ€λŠ” a_t 와 b_t 클래슀 λͺ¨λ‘ μƒμ†ν•˜λ €κ³  ν•œλ‹€β—
      • 클래슀 μ„ μ–Έ ν•œ λ‹€μŒμ— c_obj 객체λ₯Ό λ§Œλ“€μ—ˆλ‹€
      • μ„œλ‘œ λ‹€λ₯Έ 포인터도 λ§Œλ“€μ—ˆλ‹€
    • 🚨 μ΄λŸ¬ν•œ ν¬μΈν„°λŠ” λͺ¨λ‘ λ°˜λ“œμ‹œ 같은 μ£Όμ†Œλ₯Ό κ°€λ¦¬μΌœμ•Ό ν•œλ‹€
      • BUT a_ptr κ³Ό c_ptr ν¬μΈν„°λŠ” a_t 및 c_t 클래슀의 μ–΄λŠ ν–‰μœ„ ν•¨μˆ˜μ™€λ„ μ•ˆμ „ν•˜κ²Œ μ‚¬μš© κ°€λŠ₯
      • b_ptr ν¬μΈν„°λŠ” a_t 객체에 ν•΄λ‹Ήν•˜λŠ” c_t 클래슀 λ‚΄μ˜ ν•„λ“œλ₯Ό κ°€λ¦¬ν‚€λ―€λ‘œ μ‚¬μš©ν•˜κΈ° μœ„ν—˜
      • b_ptr 포인터 톡해 b_t μ•ˆμ— μžˆλŠ” ν•„λ“œλ‘œ μ ‘κ·Όν•˜λ €κ³  ν•œλ‹€λ©΄ μ •μ˜λ˜μ§€ μ•Šμ€ ν–‰μœ„λ‘œ 됨
    • μ•„λž˜λŠ” μ˜¬λ°”λ₯Έ ν•„λ“œλ₯Ό 가리킀도둝 μΊμŠ€νŒ… (λ³€ν™˜) 을 μ—…λ°μ΄νŠΈ ν•œ μ˜ˆμ‹œλ‹€

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      typedef struct {...} a_t;
      typedef struct {...} b_t;
      
      typedef struct {
      	a_t a;
      	b_t b;
      	...
      } c_t;
      
      c_t c_obj;
      a_t* a_ptr = (a_t*)&c_obj;
      // ⬇️ 밑에 λ°”λ€œ
      b_t* b_ptr = (b_t*)(&c_obj + sizeof(a_t));
      c_t* c_ptr = &c_obj;
      
      • 🚨 c_obj 의 μ£Όμ†Œμ— λŒ€ν•œ a_t 객체의 크기λ₯Ό 좔가함
        • c_t λ‚΄λΆ€μ˜ b ν•„λ“œλ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터가 λœλ‹€
        • ν˜•λ²ˆν™˜ : μžλ£Œν˜•μ„ λ³€ν™˜ν•˜κΈ° μœ„ν•΄ μ‘΄μž¬ν•˜λ©°, μ•žμ— μ˜ˆμ—μ„œλŠ” λ©”λͺ¨λ¦¬ μ£Όμ†Œμ— ν•΄λ‹Ήν•˜λŠ” 전솑값을 μˆ˜μ •ν•˜μ§€λŠ” μ•ŠμŒ!
        • ν• λ‹Ή μ΄ν›„μ—λŠ” κ²°κ΅­ 였λ₯Έμͺ½μ˜ μ£Όμ†Œκ°€ μ™Όμͺ½μœΌλ‘œ λ³΅μ‚¬λœλ‹€
  • 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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    // File name: ExtremeC_examples_chapter9_3.cpp
    // Description: Multiple inheritance in C++
    
    #include <string.h>
    
    class A {
    public:
      char a; // A
      char b[4]; // BBB
    };
    
    class B {
    public:
      char c; // C
      char d;  // D
    };
    
    class C {
    public:
      char e;  // E
      char f;  // F
    };
    
    class D : public A, public B, public C {
    public:
      char str[5];  // 1234
    };
    
    int main(int argc, char** argv) {
      D d;
      d.a = 'A';
      strcpy(d.b, "BBB");
      d.c = 'C';
      d.d = 'D';
      d.e = 'E';
      d.f = 'F';
      strcpy(d.str, "1234");
      A* ap = &d;
      B* bp = &d;
      C* cp = &d;
      D* dp = &d;
      // We need to set a break point at this line.
      return 0;
    }
    
    1
    2
    
    g++ -g ExtremeC_examples_chapter9_3.cpp -o ex9_3.out
    gdb ./ex9_3.out
    
    • 속성은 μ„œλ‘œ μΈμ ‘ν•œ 곳에 있음
      • λΆ€λͺ¨ ν΄λž˜μŠ€μ— λŒ€ν•œ μ—¬λŸ¬ 객체가 d 객체의 λ©”λͺ¨λ¦¬ λ ˆμ΄μ•„μ›ƒκ³Ό 같은 κ³³ 내뢀에 μžˆμŒμ„ λ‚˜νƒ€λƒ„
    • ap, bp, cp, dp ν¬μΈν„°λŠ” ❓
      • C++ μ—μ„œλŠ” μžμ‹ 포인터λ₯Ό λΆ€λͺ¨ ν¬μΈν„°λ‘œ ν• λ‹Ήν•  λ•Œ (μ—…μΊμŠ€νŒ…) μ••λ¬΅μ μœΌλ‘œ ν˜•λ³€ν™˜ κ°€λŠ₯
      • $4 둜 λ‚˜νƒ€λ‚˜λŠ” d 객체에 λŒ€ν•œ μ‹œμž‘ μ£Όμ†Œλ₯Ό λ³΄μ—¬μ€Œ
        • $1 둜 λ‚˜νƒ€λ‚˜λŠ” ap κ°€ κ°€λ¦¬ν‚€λŠ” μ£Όμ†Œμ™€ κ°™μŒ β‡’ C++ μ—μ„œ D 클래슀의 속성 ꡬ쑰체에 λŒ€μ‘ν•˜λŠ” 첫 번째 ν•„λ“œλ‘œμ¨ A μžλ£Œν˜•μ— λŒ€ν•œ 객체λ₯Ό λ‘”λ‹€λŠ” 점이 λͺ…확해짐
      • 포인터에 μžˆλŠ” μ£Όμ†Œμ™€ x λͺ…λ Ήμ–΄λ‘œ 얻은 κ²°κ³Όλ₯Ό ν† λŒ€λ‘œ, B μžλ£Œν˜•κ³Ό C μžλ£Œν˜•μ˜ κ°μ²΄λŠ” 객체 d에 μ†ν•˜λŠ” λ©”λͺ¨λ¦¬ λ ˆμ΄μ•„μ›ƒκ³Ό 같은 곳에 있음
      • μ•žμ˜ μ£Όμ†ŒλŠ” C++ μ—μ„œμ˜ ν˜•λ³€ν™˜μ΄ μˆ˜λ™ μž‘μ—…μ΄ μ•„λ‹ˆλΌλŠ” 점을 λ‚˜νƒ€λƒ„
      • μžλ£Œν˜•μ„ λ³€ν™˜ν•  λ•Œ μ „μ†‘ν•˜λŠ” μ£Όμ†Œμ— λŒ€ν•œ 포인터 연산을 μˆ˜ν–‰ν•  수 μžˆμŒμ„ λ³΄μ—¬μ€Œ
        • EX) bp 포인터λ₯Ό ν• λ‹Ήν•  λ•Œ, 5λ°”μ΄νŠΈ λ˜λŠ” sizeof(A) κ°€ d의 μ£Όμ†Œμ— μΆ”κ°€λœλ‹€
        • C μ—μ„œ 닀쀑 상속을 κ΅¬ν˜„ν•˜λŠ” κ³Όμ •μ—μ„œ λ°œκ²¬λ˜λŠ” 문제λ₯Ό κ·Ήλ³΅ν•˜λ €λŠ” 것..
        • C++ 이듀 ν¬μΈν„°λŠ” μ‚°μˆ  μ—°μ‚° ν•„μš” 없이 λͺ¨λ“  ν–‰μœ„ ν•¨μˆ˜ λ‚΄μ—μ„œ μ‰½κ²Œ μ‚¬μš© ν•  수 있음
        • But,, C 의 ν˜•λ³€ν™˜ 처럼 C++ 의 ν˜•λ³€ν™˜λ„ μˆ˜λ™μ μΌ 것이라 κ°€μ •ν•œλ‹€λ©΄,, λ‹€λ₯Ό κ²ƒμž„ ❗

β˜‘οΈ 9.2.3 λ‹€ν˜•μ„±

  • C μ—μ„œ λ‹€ν˜•μ μΈ ν–‰μœ„ ν•¨μˆ˜λŠ” 간단함
  • C++ μ—μ„œ λ‹€ν˜•μ„±μ„ 가지렀면 더 λ³΅μž‘ν•œ λ©”μ»€λ‹ˆμ¦˜ μ‚¬μš©ν•¨

    • 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
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      
      // ν•¨μˆ˜ 포인터 μžλ£Œν˜• μ •μ˜ν•˜κΈ°
      typedef void* (*func_1_t)(void*, ...);
      typedef void* (*func_2_t)(void*, ...);
      ...
      typedef void* (*func_n_t)(void*, ...);
      
      // λΆ€λͺ¨ ν΄λž˜μŠ€μ— λŒ€ν•œ 속성 ꡬ쑰체
      typedef struct {
       // 속성
       ...
       // ν•¨μˆ˜μ— λŒ€ν•œ 포인터
       func_1_t func_1;
       func_2_t func_2;
       ...
       func_n_t func_t;
      } parent_t;
      
      // 가상 ν–‰μœ„ ν•¨μˆ˜μ— λŒ€ν•œ κΈ°λ³Έ λΉ„κ³΅κ°œ μ •μ˜
      void* __default_func_1(void* parent, ...) { // 기본 의
      }
      void* __default_func_2(void* parent, ...) { // 기본 의
      }
      ...
      void* __default_func_n(void* parent, ...) { // 기본 의
      }
      
      // μƒμ„±μž
      void parent_ctor(parent_t *parent) {
       // 속성 μ΄ˆκΈ°ν™”ν•˜κΈ°
       ...
       // 가상 ν–‰μœ„ ν•¨μˆ˜μ— λŒ€ν•œ κΈ°λ³Έ μ •μ˜ μ„€μ •ν•˜κΈ°
       parent->func_1 = __default_func_1;
       parent->func_2 = __default_func_2;
       ...
       parent->func_n = __default_func_n;
      }
      
      // 곡용인 비가상 ν–‰μœ„ ν•¨μˆ˜
      void* parent_non_virt_func_1(parent_t* parent, ...) { // Code }
      void* parent_non_virt_func_2(parent_t* parent, ...) { // Code }
      ...
      void* parent_non_virt_func_m(parent_t* parent, ...) { // Code }
      
      // μ‹€μ œ 곡용 가상 ν–‰μœ„ ν•¨μˆ˜λ“€
      void* parent_func_1(parent_t* parent, ...) {
       return parent->func_1(parent, ...);
      }
      void* parent_func_2(parent_t* parent, ...) {
       return parent->func_2(parent, ...);
      }
      ...
      void* parent_func_n(parent_t* parent, ...) {
       return parent->func_n(parent, ...);
      }
      
      • λΆ€λͺ¨ ν΄λž˜μŠ€λŠ” 속성 ꡬ쑰체 내뢀에 ν•¨μˆ˜ 포인터에 λŒ€ν•œ λͺ©λ‘μ„ κ°–κ³  μžˆμ–΄μ•Ό 함
      • λΆ€λͺ¨ 클래슀의 μ΄λŸ¬ν•œ ν•¨μˆ˜ ν¬μΈν„°λŠ” 가상 ν•¨μˆ˜μ— λŒ€ν•œ κΈ°λ³Έ μ •μ˜λ₯Ό 가리킴
        • 그렇지 μ•ŠμœΌλ©΄ NULL κ°’ 가짐
      • μ •μ˜λœ μ˜μ‚¬ ν΄λž˜μŠ€λŠ” m μ΄λΌλŠ” 비가상 ν–‰μœ„ ν•¨μˆ˜μ™€ n μ΄λΌλŠ” 가상 ν–‰μœ„ ν•¨μˆ˜ 가짐
        • 비가상 ν•¨μˆ˜λŠ” λ‹€ν˜•μ μ΄μ§€ μ•ŠμŒ
          1
          2
          
          //κ΅¬ν˜„ λŒ€μ‹  κ°€μƒν•¨μˆ˜μ— NULL (0)값을 λŒ€μž…ν•˜λ©΄ ν•΄λ‹Ή ν•¨μˆ˜λŠ” 순수 κ°€μƒν•¨μˆ˜κ°€ λ©λ‹ˆλ‹€
          virtual void function() = 0;
          
          • 비가상 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ λ‹€μ–‘ν•œ ν–‰μœ„λ₯Ό 얻을 수 μ—†μŒ
          • 즉, 비가상 ν•¨μˆ˜μ— λŒ€ν•œ ν˜ΈμΆœμ€ λ‹¨μˆœν•œ ν•¨μˆ˜ ν˜ΈμΆœμ— μ§€λ‚˜μ§€ μ•ŠμœΌλ©°!
          • μ •μ˜ λ‚΄λΆ€μ˜ λ‘œμ§λ§Œμ„ μˆ˜ν–‰ν•  뿐 λ‹€λ₯Έ ν•¨μˆ˜λ‘œ ν˜ΈμΆœμ„ μ „λ‹¬ν•˜μ§€ μ•ŠμŒ
        • 가상 ν•¨μˆ˜λŠ” λΆ€λͺ¨ λ˜λŠ” μžμ‹ μƒμ„±μžμ— μ˜ν•΄ μ„€μ •λœ μ μ ˆν•œ ν•¨μˆ˜λ‘œ ν˜ΈμΆœμ„ λ‹€μ‹œ 전달해야 함
          1
          2
          3
          4
          5
          
          // C++μ—μ„œ 가상 ν•¨μˆ˜λŠ” virtual ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ„ μ–Έν•©λ‹ˆλ‹€.
          
          virtual function(){
            ...
          }
          
          • μƒμ†λœ 가상 ν•¨μˆ˜μ˜ 일뢀λ₯Ό μžμ‹ ν΄λž˜μŠ€κ°€ λ‹€μ‹œ μ •μ˜ν•˜λ €λ©΄ 가상 ν•¨μˆ˜ 포인터λ₯Ό μ—…λ°μ΄νŠΈ ν•΄μ•Ό 함
  • μžμ‹ ν΄λž˜μŠ€κ°€ λͺ‡λͺ‡ 가상 ν•¨μˆ˜λ₯Ό μ˜€λ²„λΌμ΄λ”© ν•˜λŠ” 법을 λ‚˜νƒ€λƒ„

    • μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ ν΄λž˜μŠ€λ‘œλΆ€ν„° 상속받은 가상 ν•¨μˆ˜λ₯Ό μ˜€λ²„λΌμ΄λ”© ν•˜λŠ” 방법

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      
      // λΆ€λͺ¨ ν΄λž˜μŠ€μ— κ΄€λ ¨λœ λͺ¨λ“  것을 ν¬ν•¨ν•˜μ„Έμš”
      
      typedef struct {
       parent_t parent;
       // μžμ‹ 속성
       ...
      } child_t;
      
      void* __child_func_4(void* parent, ...) { // μ˜€λ²„λΌμ΄λ”© μ •μ˜
      }
      void* __child_func_7(void* parent, ...) { // μ˜€λ²„λΌμ΄λ”© μ •μ˜
      }
      
      void child_ctor(child_t* child) {
       parent_ctor((parent_t*)child);
       // μžμ‹ 속성 μ΄ˆκΈ°ν™”ν•˜κΈ°
       ...
       // ν•¨μˆ˜μ— λŒ€ν•œ 포인터 μ—…λ°μ΄νŠΈ ν•˜κΈ°
       child->parent.func_4 = __child_func_4;
       child->parent.func_7 = __child_func_7;
      }
      
      // μžμ‹μ˜ ν–‰μœ„ ν•¨μˆ˜
      ...
      
      • μžμ‹ ν΄λž˜μŠ€λŠ” λΆ€λͺ¨μ˜ 속성 ꡬ쑰체 μ•ˆμ— μžˆλŠ” λͺ‡λͺ‡ 포인터에 λŒ€ν•œ μ—…λ°μ΄νŠΈλ§Œ ν•„μš”
        • C++ μ—μ„œλ„ λΉ„μŠ·ν•œ 접근법 취함
        • virtual ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄ ν–‰μœ„ ν•¨μˆ˜λ₯Ό κ°€μƒμœΌλ‘œ μ„ μ–Έ ν•  λ•Œ C++ λŠ” ν•¨μˆ˜ ν¬μΈν„°μ˜ 배열을 λ§Œλ“ λ‹€
      • 각각의 가상 ν•¨μˆ˜μ— λŒ€ν•΄ ν•¨μˆ˜ 포인터 속성 ν•˜λ‚˜λ₯Ό μΆ”κ°€ν–ˆμŒ
        • C++ μ—μ„œλŠ” μ΄λŸ¬ν•œ 포인터λ₯Ό λ‘λŠ”λ° 더 μ˜λ¦¬ν•¨
          • 🚨 가상 ν…Œμ΄λΈ” λ˜λŠ” vtable μ΄λΌλŠ” λ°°μ—΄λ§Œ μ‚¬μš©ν•¨
          • 가상 ν…Œμ΄λΈ”μ€ 객체가 μƒμ„±λ˜λ €κ³  ν•  λ•Œ λ§Œλ“€μ–΄μ§„λ‹€
          • 가상 ν…Œμ΄λΈ”μ€ 기초 ν΄λž˜μŠ€μ— λŒ€ν•œ μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  λ•Œ 처음 μΆ”κ°€ 됨
          • κ·Έ 뒀에, μžμ‹ 클래슀의 μƒμ„±μžμ˜ 일뢀가 λœλ‹€
          • 가상 ν…Œμ΄λΈ”μ€ μƒμ„±μžμ—μ„œλ§Œ μΆ”κ°€λ˜λŠ” 만큼, λΆ€λͺ¨ 및 μžμ‹ 클래슀 λͺ¨λ‘ μƒμ„±μžμ—μ„œ λ‹€ν˜•μ  λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ§€ μ•Šμ•„μ•Ό 함
          • 포인터가 μ—…λ°μ΄νŠΈ λ˜μ§€ μ•Šμ•˜μ„ μˆ˜λ„ 있고, ν‹€λ¦° μ •μ˜λ₯Ό 가리킬 수 있음

β˜‘οΈ 9.2.4 좔상 클래슀

  • C++ μ—μ„œ μΆ”μƒν™”λŠ” 순수 가상 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 있음
  • C++ μ—μ„œ 멀버 ν•¨μˆ˜λ₯Ό 가상 ν•¨μˆ˜λΌκ³  μ •μ˜ν•˜κ³  이λ₯Ό 0으둜 λ‘”λ‹€λ©΄, 순수 가상 ν•¨μˆ˜λ₯Ό μ •μ˜ ν•œ 것!

    • C++의 Eatable μΈν„°νŽ˜μ΄μŠ€

      1
      2
      3
      4
      5
      6
      7
      
      enum class Taste { Sweet, Sour };
      
      // μΈν„°νŽ˜μ΄μŠ€
      class Eatable {
      public:
      	virtual Taste GetTaste() = 0;
      }
      
      • Eatable 클래슀 내뢀에 0 으둜 μ„€μ •ν•œ GetTaste λΌλŠ” 가상 ν•¨μˆ˜κ°€ 있음
      • GetTaste λŠ” 순수 가상 ν•¨μˆ˜ 이며, 전체 클래슀λ₯Ό 좔상화 함
      • Eatable μžλ£Œν˜•μœΌλ‘œλΆ€ν„° 더 이상 객체λ₯Ό 생성 ν•  수 μ—†μœΌλ©°, C++ κ°€ 이λ₯Ό ν—ˆμš©ν•˜μ§€ μ•ŠμŒ
        • Eatable 은 μΈν„°νŽ˜μ΄μŠ€μΈλ°, Eatable 의 λͺ¨λ“  멀버 ν•¨μˆ˜κ°€ μˆœμˆ˜ν•˜κ²Œ 가상이기 λ•Œλ¬Έ
      • 이 ν•¨μˆ˜λŠ” μžμ‹ ν΄λž˜μŠ€μ— μ˜ν•΄ μ˜€λ²„λΌμ΄λ”© 될 수 있음
    • C++의 Eatable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” μžμ‹ 클래슀 (GetTaste ν•¨μˆ˜λ₯Ό μ˜€λ²„λΌμ΄λ”© ν•˜λŠ” 클래슀)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      enum class Taste { Sweet, Sour };
      
      // μΈν„°νŽ˜μ΄μŠ€
      class Eatable {
      public:
      	virtual Taste GetTaste() = 0;
      }
      
      class Apple : public Eatable {
      public:
       Taste GetTaste() override {
       return Taste::Sweet;
       }
      };
      
      • 순수 가상 ν•¨μˆ˜λŠ” 가상 ν•¨μˆ˜μ™€ μƒλ‹Ήνžˆ λΉ„μŠ·ν•¨
      • μ‹€μ œ μ •μ˜μ— λŒ€ν•œ μ£Όμ†ŒλŠ” 가상 ν•¨μˆ˜μ™€ λ§ˆμ°¬κ°€μ§€ λ°©μ‹μœΌλ‘œ 가상 ν…Œμ΄λΈ” 내에 있음
      • 순수 가상 ν•¨μˆ˜μ— λŒ€ν•œ ν¬μΈν„°μ˜ μ΄ˆκΉƒκ°’μ€ NULL
        • 일반적인 가상 ν•¨μˆ˜μ˜ ν¬μΈν„°μ™€λŠ” 닀름
        • 일반적인 가상 ν•¨μˆ˜μ˜ ν¬μΈν„°λŠ” 생성이 μ§„ν–‰λ˜λŠ” λ™μ•ˆ κΈ°λ³Έ μ •μ˜λ₯Ό κ°€λ¦¬μΌœμ•Ό 함
      • 좔상 μžλ£Œν˜•μ— λŒ€ν•΄μ„œ 아무것도 μ•Œμ§€ λͺ»ν•˜λŠ” C μ»΄νŒŒμΌλŸ¬μ™€ 달리 - C++ μ»΄νŒŒμΌλŸ¬λŠ” 좔상 μžλ£Œν˜•μ„ μ•Œκ³  있음 - λ§Œμ•½, 좔상 μžλ£Œν˜•μœΌλ‘œλΆ€ν„° 객체λ₯Ό μƒμ„±ν•˜λ €κ³  ν•œλ‹€λ©΄ 컴파일 였λ₯˜ λ°œμƒ

        순수 가상 ν•¨μˆ˜μ— λŒ€ν•œ ν¬μΈν„°μ˜ μ΄ˆκΉƒκ°’μ€ NULL

        • 일반적인 가상 ν•¨μˆ˜μ˜ ν¬μΈν„°μ™€λŠ” 닀름
        • 일반적인 가상 ν•¨μˆ˜μ˜ ν¬μΈν„°λŠ” 생성이 μ§„ν–‰λ˜λŠ” λ™μ•ˆ κΈ°λ³Έ μ •μ˜λ₯Ό κ°€λ¦¬μΌœμ•Ό 함

        🚨 좔상 ν΄λž˜μŠ€λŠ” λ¨Όμ € 상속을 톡해 νŒŒμƒ 클래슀λ₯Ό λ§Œλ“€κ³ , λ§Œλ“  νŒŒμƒ ν΄λž˜μŠ€μ—μ„œ 순수 가상 ν•¨μˆ˜λ₯Ό λͺ¨λ‘ μ˜€λ²„λΌμ΄λ”©ν•˜κ³  λ‚˜μ„œμ•Ό λΉ„λ‘œμ†Œ νŒŒμƒ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 있게 λ©λ‹ˆλ‹€. (ν•˜μ§€λ§Œ 좔상 클래슀 νƒ€μž…μ˜ 포인터와 μ°Έμ‘°λŠ” λ°”λ‘œ μ‚¬μš© κ°€λŠ₯)

⭐ 9.3 마무리

  • 좔상 μžλ£Œν˜•κ³Ό μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ‹€λ£Έ
    • 이λ₯Ό 톡해 μΈν„°νŽ˜μ΄μŠ€ λ˜λŠ” 좔상적인 클래슀λ₯Ό κ°€μ§ˆ 수 있음
    • 이 뢀뢄적인 좔상 ν΄λž˜μŠ€λŠ” λ‹€ν˜•μ„±μ„ κ°–λŠ” 더 ꡬ체적인 μžμ‹ 클래슀 및 λ‹€λ₯Έ ν–‰μœ„λ₯Ό λ§Œλ“€ λ•Œ μ‚¬μš© κ°€λŠ₯
  • OOP κΈ°λŠ₯을 λ„μž…ν•˜κΈ° μœ„ν•΄ Cμ—μ„œ μ‚¬μš©ν•˜λŠ” 기법에 κ΄€ν•œ 좜λ ₯ κ²°κ³Όλ₯Ό g++ 의 좜λ ₯ 결과와 λΉ„κ΅ν•˜κ³ , κ·Έ κ²°κ³Όκ°€ μ–Όλ§ˆλ‚˜ λΉ„μŠ·ν•œμ§€ μ„€λͺ…함 (맀우 μœ μ‚¬ν•¨)
  • 가상 ν…Œμ΄λΈ” μƒμ„Ένžˆ λ‹€λ£Έ
  • 순수 가상 ν•¨μˆ˜ (C++ κ°œλ…μ΄μ§€λ§Œ C 에도 ν•΄λ‹Ήν•˜λŠ” κ°œλ… 있음) κ°€ κΈ°λ³Έ μ •μ˜λ₯Ό 갖지 μ•ŠλŠ” 가상 ν–‰μœ„λ₯Ό μ„ μ–Έν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” 방법 λ³΄μ—¬μ€Œ
This post is licensed under CC BY 4.0 by the author.