C++프로그래밍

Download Report

Transcript C++프로그래밍

이기자 C++프로그래밍
Part 2: C++언어
5 장 : 클래스 기초
1
학습내용
5장 클래스 기초
5.1 구조체 자료형의 진화
5.2 추상적인 자료형 클래스
5.3 클래스 멤버의 접근제어
5.4 다양한 클래스 예제들
5.5 생성자함수와 소멸자 함수
5.6 객체지향 프로그래밍의 기본개념
5.7 프로그래밍실습
(참고: 5장의 경우 전체적인 양이 많으므로, 5.6 절은 학생
들이 reading assignment로 하거나, 나중에 시간이 여유
가 있는 경우에 학습해도 된다. )
2/97
5.1 구조체 자료형의 진화
3
5.1 구조체자료형의 진화
5.1.1 구조체자료형의 유용성

관련 있는 데이터를 하나의 자료형으로 묶을 수 있다.

따라서, 프로그램의 구현 및 관리가 용이해진다.

함께 움직이는 데이터들을 묶어주는 효과!
4/97
5.1.2 구조체 자료형의 개선점

C 언어의 구조체에 대한 불만

모든 사용자 정의 자료형에 대한 불만

기본 자료형으로 인식해 주지 않는다.
/* Structure1.c */
1: #include <stdio.h>
2:
3: struct Student{
// Student 라는 이름의 사용자 정의 자료형
4: char name[10]; // 이름
5: char address[20]; // 주소
6: int Year; // 학년
7: };
8:
9: int main()
10: {
11: int a = 10;
12: Student s; // struct Student s;
13:
14: return 0;
15: }
C++의 철학과
맞물리면?

Structure1.c 또는 structure1.cpp로
컴파일 해 보자?
5/97
5.1.3 클래스의 등장배경

프로그램에 대한 정의




프로그램 = 데이터 + 데이터를 조작하는 함수
예) “ Hello World”를 모니터에 출력하는 프로그램
Hello World: 데이터, printf 또는 cout : 함수
잘 구성된 프로그램들은 데이터만을 가지고 부류를 형성하는 것이
아니라, 데이터를 조작하는 루틴, 즉 함수와 더불어 부류를 형성하
고 있다.
6/97
[3] 클래스의 등장배경
1: /** Structure2.cpp **/
2:
3: #include <iostream>
4: using namespace std;
5:
6:
7: //사원을 위한 구조체
8: struct Employee
9: {
10: char name[10]; /* 이름 */
11: char personID[20]; /* 주민등록번호 */
12: char address[30]; /* 주소 */
13: int salary; /* 월 급여액 */
14: };
15:
16: void setAddress(Employee &emp, char* _address) // 주
소를 수정한다.
17: {
18:
strcpy(emp.address, _address);
19: }
20:
21: void setSalary(Employee &emp, int _salary) // 급여액을
수정한다.
22: {
23:
emp.salary = _salary;
24: }
25:
26: void display(Employee &emp) // 콘솔화면에 사원정보를 출
력한다.
27: {
28: cout << emp.name << ", " << emp.personID << ", " <<
29: emp.address << ", " << emp.salary << "만원" << endl;
30: }
31:
32:
33: int main()
34: {
35: Employee Hong={"홍길동", "700815", "충남천안시", 500};
36: Employee Park={"박찬호", "680121","서울시",1000};
37:
38: display(Hong);
39: display(Park);
40:
41: setAddress(Hong,"서울시강남구"); // 홍길동 사원의 주소
변경
42: setSalary(Park,200); // 박찬호 사원의 급여 변경
43:
44: display(Hong);
45: display(Park);
46:
47:
return 0;
48: }
7/97
[3] 클래스의 등장배경



C++언어에서는 struct 키워드를 사용하지 않고, 일반 기본
자료형 변수 선언과 같이 Employee 구조체 변수를 선언하
고 있다.
참고로 C++언어는 C언어를 포함함으로 다음과 같이
struct 키워드를 사용해도 된다.
Structure2.cpp의 실행결과는 다음과 같다.
8/97
[3] 클래스의 등장배경

함수를 넣으면 좋은 구조체

데이터들이 부류를 형성하면, 이 데이터들을 조작하는 함수들도 구성이 되는
데, 이것도 하나의 부류로 인정을 하고, 함께 관리를 해 주면 프로그램이 한결
수월해 진다.
9/97
[3] 클래스의 등장배경
10/97
[3] 클래스의 등장배경
1: /** Structure2-1.cpp **/
2:
3: #include <iostream>
4: using namespace std;
5:
6: //사원을 표현하는 새로운 구조체 자료형
7: struct Employee
8: {
9: char name[10]; /*이름*/
10: char personID[20]; /*주민등록번호*/
11: char address[30]; /*주소*/
12: int salary; /*월 급여액*/
13:
14: void setAddress(char* _address) // 주소를 수정한다.
15: {
16:
strcpy(address, _address);
17: }
18: void setSalary(int _salary) // 급여액을 수정한다.
19: {
20:
salary = _salary;
21: }
22: void display() // 콘솔화면에 사원정보를 출력한다.
23: {
24:
cout << name << ", " << personID << ", " << address
<< 25: ", " << salary << "만원" << endl;
26: }
27: };
28:
29: int main()
30: {
31: Employee Hong={"홍길동", "700815", "충남천안시", 500};
32: Employee Park={"박찬호", "680121","서울시",1000};
33:
34: Hong.display();
35: Park.display();
36:
37: Hong.setAddress("서울시강남구"); // 홍길동 사원의 주소
변경
38: Park.setSalary(200); // 박찬호 사원의 급여 변경
39:
40: Hong.display();
41: Park.display();
42:
43: return 0;
44:}
11/97
[3] 클래스의 등장배경
12/97
[3] 클래스의 등장배경
struct Account {
char accID[20];
char secID[20];
char name[20];
int balance;
};
struct Account {
char accID[20];
char secID[20];
char name[20];
int balance;
void Deposit(int money){
balance+=money;
}
void Withdraw(int money){
balance-=money;
}
void Deposit(Account &acc, int money)
{
acc.balance+=money;
}
void Withdraw(Account &acc, int money)
{
acc.balance-=money;
}
};
13/97
1: /* Example.cpp */
2: #include <iostream>
3: using namespace std;
4:
5: struct Account {
6: char accID[20]; // 계좌 번호
7: char secID[20]; // 비밀 번호
8: char name[20]; // 이 름
9: int balance;
// 잔 액
10:
11: void Deposit(int money){
12:
balance+=money;
13: }
14: void Withdraw(int money){
15:
balance-=money;
16: }
17: };
18:
19: int main(void)
20: {
21: Account yoon={"1234", "2321", "yoon", 1000};
22:
23: yoon.Deposit(100);
24: cout<<"잔 액 : "<<yoon.balance<<endl;
25:
26: yoon.Withdraw(200);
27: cout<<"잔 액 : "<<yoon.balance<<endl;
28:
29: return 0;
30: }
14/97
[3] 클래스의 등장배경
struct Account {
char accID[20];
char secID[20];
char name[20];
int balance;
void Deposit(int money){
balance+=money;
}
void Withdraw(int money){
balance-=money;
}
};
int main(void)
{
Account yoon={"1234", "2321", "yoon", 1000};
yoon.Deposit(100);
cout<<"잔 액 : "<<yoon.balance<<endl;
return 0;
}
그림 : 함수가 존재하는 구조체 변수
15/97
[3] 클래스 등장배경

구조체가 아니라 클래스(Class)

클래스 = 멤버 변수 + 멤버 함수

변수가 아니라 객체(Object: 완전한 대상체)

객체란 현실세계에 존재하는 주변의 모든 것들(자동차, 강아지, 사람,
건물 등등)을 뜻하는 것으로서 완전한 대상체라는 의미를 지닌다.
16/97
// Structure2-2.cpp
1: //사원을 표현하는 새로운 구조체 자료형
2: class Employee
3: {
4: public:
5:
char name[10]; /*이름*/
6:
char personID[20]; /*주민등록번호*/
7:
char address[30]; /*주소*/
8:
int salary; /*월 급여액*/
9:
10: void setAddress(char* _address) // 주소를 수정한다.
11: {
12:
strcpy(address, _address);
13: }
14: void setSalary(int _salary) // 급여액을 수정한다.
15: {
16:
salary = _salary;
17:
}
18:
void display() // 콘솔화면에 사원정보를 출력한다.
19: {
20:
cout << name << ", " << personID << ", " << address << 21: ", " << salary
<< "만원" << endl;
22: }
23: };
17/97
5.2 추상적인 자료형 클래스
18
5.2.1 클래스의 정의

사물의 관찰 이후의 데이터 추상화

현실 세계의 사물을 데이터적인 측면과 기능적인 측면
을 통해서 정의하는 것
특징 1. 발이 네 개
특징 2. 코의 길이가 5미터 내외
특징 3. 몸무게는 1톤 이상
특징 4. 코를 이용해서 목욕을 함
특징 5. 코를 이용해서 물건을 집기도 함
19/97
5.2.1 클래스의 정의

class 선언의 형식은 구조체의 선언과 유사하며, 일반적인
형식은 다음과 같다.
class class-name{
// 전용(private) 함수와 변수 선언
public: // 접근 제어 키워드
// 공용(public) 함수와 변수 선언
} object-list;
20/97
5.2.1 클래스의 정의

간단한 클래스 예제
class myclass {
int a; // myclass의 private 멤버변수
public:
int b; // myclass의 public 멤버변수
void set_a(int num){ // 멤버함수
a = num;
}
int get_a(){
// 멤버함수
return a;
}
};
myclass ob1, ob2; // myclass 형의 객체 선언 또는 객체 인스턴스화
21/97
[간단한 클래스 예제프로그램 1]
/* class1.cpp */
#include <iostream>
using namespace std;
class myclass {
// myclass의 전용변수
int a;
public:
void set_a(int num){
a = num;
}
int get_a(){
return a;
}
};
int main()
{
myclass ob1, ob2;
ob1.set_a(10); // 멤버함수 set_a를 호출하고, 매개변수 10을 전달
ob2.set_a(99); // 멤버함수 set_a를 호출하고, 매개변수 99를 전달
cout << ob1.get_a() << "\n";
cout << ob2.get_a() << "\n";
return 0;
}
22/97
[간단한 클래스 예제프로그램 2]
/* class2.cpp */
1: #include <iostream>
2: using namespace std;
3:
4: //Point 클래스를 정의한다.
5: class Point
6: {
7: private:
8:
int cx, cy; // private 멤버변수
9: public:
10:
void SetPoint(int x, int y) // Point 클래스의 멤버 함수
11: {
12:
cx = x;
13:
cy = y;
14:
}
15:
void Display() // Point 클래스의 멤버 함수
16: {
17:
cout << 'c' << cx << ',' << cy << ')' << endl;
18:
}
19:
20: };
21:
22: void main()
23: {
24:
Point a, b; // Point 객체 생성
25:
a.SetPoint(2, 3); // Point 객체 a를 초기화한다.
26:
b.SetPoint(4, 5); // Point 객체 b를 초기화한다.
27:
28:
a.Display(); // Point 객체 a를 화면에 출력한다.
29:
b.Display(); // Point 객체 b를 화면에 출력한다.
30:
31:
return 0;
32: }
23/97
[클래스요약]




기존의 C언어에서의 구조체를 정의하는 것과
달라진 점을 다시한번 요약하면 크게 세 가지
로 요약할 수 있다.
첫째, class 라는 키워드를 사용해서 정의한다.
둘째, public, private, protected와 같은 접근
제어와 관련한 키워드를 멤버변수와 멤버함수
에 사용한다.
셋째, 멤버함수 역시 멤버변수들과 함께 포함
되어 정의될 수 있다.
24/97
5.2.2 멤버함수의 장점

클래스 정의에서 멤버함수를 사용하는 장점 또는 이유를
정리하면 다음과 같다.





프로그램이라는 것은 넓은 의미로 데이터와 데이터를 조작하는 함
수라고 정의할 수 있다. 그래서 클래스 그 자체가 하나의 독립적인
프로그램이라고 할 수 있다.
클래스의 멤버함수는 클래스의 멤버변수를 보호하고, 데이터를 은
닉할 수 있고, 처리할 수 있는 기능을 제공한다.
멤버함수를 사용하면 클래스의 데이터 구조를 쉽게 변경할 수 있다.
멤버함수를 사용하면 private 데이터에 접근하게 함으로써, 객체지
향프로그램의 장점인 데이터 은닉화기능을 제공할 수 있다.
연산자 중복(operator overloading)을 통해 객체에 연산기능을 부
여할 수 있다. (이 부분은 향후 C++를 더 배워가면서 이해할 수 있
을 것이다.)
25/97
5.2.3 멤버함수의 위치


클래스 멤버함수는 클래스 내부 또는 외부에 정의할 수 있
다.
앞에서 정의된 Point 클래스의 멤버함수를 클래스외부에
서 정의하면 다음과 같다.
멤버함수를 클래스 밖에서 정의하려면 다음과 같은 두 가
지를 하면 된다.
● 클래스 정의 안에서는 멤버 함수의 원형만 남겨둔다.
● 클래스 정의 밖에서는 범위 지정 연산자(::)를 사용해서
함수를 정의한다.

1: //Point 클래스를 정의한다.
2: class Point
3: {
4: private:
ret-type class-name::func-name(parameter-list)
5:
int cx, cy; // private 멤버변수
{
6: public:
// 함수의 몸체
7:
void SetPoint(int x, int y); // 멤버함수
}
8:
void Display(); //멤버함수
9: };
10:
11: void Point::SetPoint(int x, int y) // Point 클래스의 멤버함수 외부정의
12: {
13: cx = x;
14: cy = y;
15: }
16:
17: void Point::Display() // Point 클래스의 멤버함수 외부정의
18: {
19:
cout << 'c' << cx << ',' << cy << ')' << endl;
20: }
26/97
5.2.4 멤버함수 안에서의 이름충돌

종종 실수 할 수 있는 내용으로 멤버함수 안에서 정의한 변
수와 멤버 변수의 이름이 같은 경우 어떠한 현상이 발생하
는 지 다음 예제를 통하여 확인해 보자.
1: /* Class3.cpp */
2: #include <iostream>
3: using namespace std;
4:
5: // Point 클래스를 정의
6: class Point
7: {
8: public:
9:
int x, y; // 멤버변수 정의
10: void Display(); // 멤버함수 정의
11: };
12:
13: // 멤버함수 외부정의
14: void Point::Display()
15: {
16: int x = 300; // 멤버변수와 이름이 같은 지역변
수 선언
17: cout << "x=" << x <<"," <<"y=" << y << endl;
18: }
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
int main()
{
Point p1, p2; // 객체를 생성한다.
//p1, p2의 내부 멤버변수를 초기화한다.
p1.x = 100;
p1.y = 100;
p2.x = 200;
p2.y = 200;
// p1, p2의 내용을 출력한다.
p1.Display();
p2.Display();
cout << "p1.x=" << p1.x << endl;
cout << "p2.x=" << p2.x <<endl;
return 0;
}
27/97
5.2.5 클래스와 객체(object)
■ 특징 1: 사원은 이름을 가지고 있다.
■ 특징 2: 사원은 주민번호를 가지고 있다.
■ 특징 3: 사원은 주소를 가지고 있다.
■ 특징 4: 사원은 급여를 받는다.
■ 특징 5: 사원은 주소를 변경할 수 있다.
■ 특징 6: 사원의 급여는 변경될 수 있다.
■ 특징 7: 사원은 회사를 퇴사할 수 있다.
28/97
5.2.5 클래스와 객체(object)
29/97
5.2.5 클래스와 객체(object)
30/97
5.2.5 클래스와 객체(object)

데이터 추상화 이후의 클래스화

추상화된 데이터를 가지고 사용자 정의 자료형을 정의
하는 것
그림: 데이터 추상화
그림 : 은행계좌의 클래스화
31/97
5.2.5 클래스와 객체(object)

클래스화 이후의 인스턴스화

클래스 기반의 객체(Object) 생성
그림 4-9 : 클래스의 객체화 또는 인스턴스화
32/97
5.2.5 클래스와 객체(object)
33/97
1: /* Student.cpp */
2: #include<iostream>
3: using namespace std;
4:
5: class Student{
6:
char Name[15]; // 학생 이름
7:
int Id_number; // 학번
8:
char Major[15]; // 전공
9: public:
10:
Student(char *n,int snum,char *m) // 생성자
(constructor)
11:
{
12:
strcpy(Name,n);
13:
Id_number = snum;
14:
strcpy(Major,m);
15:
}
16:
void display()
17:
{
18:
cout<<"이름 : "<<Name<<", 학번 :
"<<Id_number<<",
전공 :"
<<Major<< endl;
19:
}
20:
21:
void sugang(Student a1){
22:
cout << a1.Name << " 수강신청 관련 내용 "
<< endl;
23:
}
24:
25:
void grade(Student a2){
26:
cout << a2.Name << " 학생성적 관련 내용 "
<< endl;
27:
}
28:
29: };
30:
31: void main()
32: {
33:
Student Hong("홍길동",2001160032,"멀티
미디어");
34:
Student Kim("김삼순", 2005010016, "인터
넷공학");
35:
36:
Hong.display();
37:
Kim.display();
38:
39:
Hong.sugang(Hong);
40:
Hong.grade(Hong);
41:
42: }
34/97
5.3 클래스멤버의 접근제어
35
5.3 클래스 멤버의 접근 제어

클래스의 내부 접근과 외부 접근
class Counter {
public:
int val;
void Increment(void)
{
val++;
}
};
int main(void)
{
Counter cnt;
cnt.val=0;
cnt.Increment();
cout<<cnt.val<<endl;
return 0;
}
//내부 접근
//외부 접근
//외부 접근
//외부 접근
36/97
5.3 클래스 멤버의 접근 제어
const int OPEN=1;
const int CLOSE=2;
class Door{
private:
int state;
public:
void Open(){ state=OPEN; }
void Close(){ state=CLOSE; }
void ShowState(){ …생략… }
};
int main()
{
Door d;
//d.state=OPEN;
d.Open();
d.ShowState();
return 0;
}
37/97
5.4 다양한 클래스 예제들
38
1: /* Date.cpp */
2: #include <iostream>
3: using namespace std;
4:
5: class Date
6: {
7:
int Year, Month, Day; // Private 멤버 변수
8: public:
9:
void SetDate(int yy, int mm, int id);
10:
void Display();
11:
int Compare(Date dt);
12:
int Input();
13: };
14:
15: void Date::SetDate(int yy, int mm, int dd) //
SetDate() 함수 정의
16: {
17: Year = yy;
18: Month = mm;
19: Day = dd;
20: }
21:
22: void Date::Display()
23: {
24: cout << Year << ',' << Month << ',' << Day;
25: }
26:
27: int Date::Compare(Date dt)
28: {
29: if(Year > dt.Year)
30:
return 1;
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:
else if(Year < dt.Year)
return -1;
else if(Month > dt.Month)
return 1;
else if(Month < dt.Month)
return -1;
else if(Day > dt.Day)
return 1;
else if(Day < dt.Day)
return -1;
else
return 0;
}
int Date::Input()
{
cin >> Year >> Month >> Day;
if(Year > 0 && Month >0 && Day > 0)
return 1;
else
return 0;
}
void main()
{
Date aDate, bDate;
aDate.SetDate(1950, 6, 25);
while(bDate.Input()){
if(aDate.Compare(bDate) >= 0)
cout << "1950년 6월 25일 이전임 \n";
else
cout << "1950년 6월 25일 이후임 \n";
}
}
39/97
// 스택 클래스 예제 프로그램
#include <iostream>
using namespace std;
#define SIZE 10
// 문자들을 저장하기 위한 스택 클래스를 선언한다.
class stack{
char stck[SIZE]; // 스택을 위한 기억장소
int tos; // 스택의 탑 인덱스
public:
void init(); // 스택을 초기화한다
void push(char ch); // 스택에 문자를 삽입한다
char pop(); // 스택에서 문자를 꺼낸다
// 하나의 문자를 꺼낸다
char stack::pop() {
if (tos == 0) {
cout << "Stack is empty";
return 0; // 스택이 빈 경우에는 널(null)을 반환한다.
}
tos--;
return stck{tos};
}
int main()
{
stack s1, s2; // 두 개의 스택 객체를 생성한다
};
int i;
// 스택을 초기화한다
void stack:init()
{
tos = 0;
}
// 스택을 초기화한다
s1.init();
s2.init();
s1.push('a');
s2.push('x');
s1.push('b');
s2.push('y');
s1.push('c');
s2.push('z');
// 하나의 문자를 삽입한다
void stack::push (char ch)
{
if (tos == SIZE) {
cout << "Stack is full";
for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
return;
}
stck[tos] = ch;
tos++;
return 0;
}
}
40/97
41/97
[연습문제 5-1]
계산기 기능을 하는 Calculator라는 이름의 클래스를 작성해 보자. 기본적으로 지니고 있는 기능은 덧셈, 뺄셈, 곱셈 그리고 나눗셈이
며, 연산을 할 때마다 어떠한 연산을 몇 번 했는지 기록되어야 한다. 다음에 제공되는 main 함수와 출력결과를 통해서 요구되는
Calculator 클래스를 디자인 해 보자.
단, 멤버변수는 private로, 멤버함수는 public으로 선언을 하자.
main 함수의 예
--------------------------------------------------------int main(void)
{
Calculator cal; // 멤버변수들은 쓰레기 값으로 초기화 한다.
cal.Init(); // 멤버 변수 초기화
cout << "3+5 = " << cal.Add(3,5) << endl;
cout << "3/5 = " << cal.Div(3,5) << endl;
cout << "12-4 = " << cal.Min(12,4) << endl;
cout << "12/4 = " << cal.Div(12,4) << endl;
cal.ShowOpCount();
return 0;
}
------------------------------------------------------------실행결과
---------------------------------------------------------3+5 = 8
3/5 = 0.6
12-4 = 8
12/4 = 3
덧셈: 1 뺄셈: 1 곱셈: 0 나눗셈: 2
----------------------------------------------------------
42/97
[연습문제 5-2]
Printer라는 이름의 클래스를 디자인하자. Printer 클래스는 두 가지 기능을 지닌다. 그 중 첫 번째는 문자열을 설
정할 수 있는 기능이고, 두 번째 기능은 설정되어 있는 문자열을 출력하는 기능이다. 다음에 제공되는 main
함수와 출력결과를 통해서 요구되는 Printer 클래스를 디자인해 보자. 이번에도 멤버변수는 private로, 멤버
함수는 public으로 선언을 하자.
main 함수의 예
---------------------------------------------------------int main(void)
{
Printer pnt;
pnt.SetString("Hello World! ");
pnt.ShowString();
pnt.SetString("I Love C++");
pnt.ShowString();
return 0;
}
------------------------------------------------------------실행결과
---------------------------------------------------------Hello World!
I Love C++
----------------------------------------------------------
43/97
[연습문제 5-3]
문자(character)를 저장하는 stack 예제를 이용
하여 문자뿐만 아니라, 정수(integer), 실수
(double)도 함께 저장할 수 있는 stack이 되도
록 수정하라. push, pop 함수 오버로딩을 이
용하여 stack 예제를 수정하고, 그 사용 예를
보여라.
(사용 예는 push 함수를 이용하여 차례로, 'a', 1,
'b', 1.5, 'c', 'd'를 stack에 저장한 후, pop 함
수를 이용하여 저장된 내용을 차례대로 보이세
요.)
44/97
5.5 생성자함수와 소멸자함수
45
5.5.1 생성자함수의 필요성
1: /* Person1.cpp */
2: #include<iostream>
3: using namespace std;
4:
7: class Person
8: {
9:
char name[10];
10:
char phone[10];
11:
int age;
12:
13: public:
14: void ShowData();
15: };
16:
17: void Person::ShowData()
18: {
19: cout<<"name: "<<name<<endl;
20: cout<<"phone: "<<phone<<endl;
21: cout<<"age: "<<age<<endl;
22: }
23:
24: int main()
25: {
26:
Person p={"KIM", "013-113-1113", 22}; //초기화
27:
p.ShowData();
28:
29: return 0;
30: }

긴 프로그램의 경우 프로그램 초기화 부분이
필요

객체 생성과 동시에 객체에 대한 초기화 필요

Person1.cpp의 26번째 줄은 에러 발생

main 함수 내에서의 객체초기화 할 수 없다.
이유는?

초기화 할 수 있는 방법?

public 변수 선언 -> 정보 은닉화에 위배

멤버 함수를 통한 초기화 -> 생성자함수
46/97
5.5.1 생성자함수의 필요성
1: /* Person2.cpp */
2: #include<iostream>
3: using namespace std;
4:
7: class Person
8: {
9:
char name[10];
10:
char phone[10];
11:
int age;
12: public:
13: void ShowData();
14: void SetData(char* _name, char* _phone, int _age);
15: };
16:
17: void Person::ShowData()
18: {
19: cout<<"name: "<<name<<endl;
20: cout<<"phone: "<<phone<<endl;
21: cout<<"age: "<<age<<endl;
22: }
23:
24: void Person::SetData(char* _name, char* _phone, int _age)
25: {
26: strcpy(name, _name)
27: strcpy(phone, _phone)
28: age = _age;
29: }
30:
31: int main()
32: {
33:
Person p;
34:
p.SetData("Cho", "041-560-1491", 36);
35:
p.ShowData(); 36:
37:
return 0;
38: }

객체초기화는 가능하지만, 객체 생성
과 동시에 초기화는 아니다.

프로그래머는 객체 생성 후 초기화 하
기위해 항상 SetData 함수를 기억하고
이를 사용해야 하는 번거로움이 있다.

객체를 생성과 동시에 초기화할 수 있
는 메커니즘을 제공 -> 생성자 함수
(constructor) 제공

참고로 다음과 같은 초기화는 허용안
됨.
class AAA
{
int a = 10;
char b = 'c';
}

생성자 함수는 클래스의 한 부분이면
서 클래스와 같은 이름을 가지며, 리턴
값이 없다.
47/97
5.5.1 생성자함수의 필요성
// myclass.cpp
1: #include<iostream>
2: using namespace std;
3:
4: class myclass {
5:
int a;
6: public:
7:
myclass(); // 생성자 함수
8:
void show();
9: };
10:
11: myclass::myclass()
12: {
13: cout << "This is a constructor function \n";
14: a = 10;
15: }
16:
17: void myclass::show()
18: {
19:
cout << "a: " << a;
20: }
21:
22: int main()
23: {
24: myclass ob;
25: ob.show();
26: return 0;
27: }
생성자 함수의 외형적인 특징

생성자는 함수이다.

생성자 함수의 함수명은 클래스의 이
름과 같은 이름을 가진다.

리턴 값도 없고, 리턴 타입도 선언되
지 않는다.

주로 객체 생성시 객체 멤버들에 대한
초기화 기능을 한다.

컴파일시 컴파일러에 의하여 자동으
로 실행된다 ?
48/97
5.5.2 객체 생성과정과 생성자 함수
1: /* Constructor1.cpp */
2: #include<iostream>
3: using namespace std;
4:
5: const int SIZE=20;
6:
7: class myclass
8: {
9:
int i, j;
10: public:
11:
myclass() //생성자 함수.
12:
{
13:
cout<<"생성자 함수 호출"<<endl;
14:
i=10, j=20;
15:
}
16:
void ShowData()
17:
{
18:
cout<<"i="<<i<<' '<<"j="<<j<<endl;
19:
}
20: };
21:
22: int main()
23: {
24: myclass a; // 객체 생성
25: a.ShowData();
26:
27: return 0;
28: }

실행결과는 다음과 같다.
------------------------------------생성자 함수 호출
i = 10 j = 20
-------------------------------------
49/97
5.5.2 객체 생성과정과 생성자 함수
1: /* Constructor2.cpp */
2: #include<iostream>
3: using namespace std;
4:
5: const int SIZE=20;
6:
7: class myclass
8: {
9:
int i, j;
10: public:
11:
myclass(int a, int b) //생성자 함수.
12:
{
13:
i = a;
14:
j = b;
15:
}
16:
void ShowData()
17:
{
18:
cout<<"i="<<i<<' '<<"j="<<j<<endl;
19:
}
20: };
21:
22: int main()
23: {
24: myclass a(100, 200); // 객체 생성과 함께 초기화
25: a.ShowData();
26:
27: return 0;
28: }
50/97
5.5.2 객체 생성과정과 생성자 함수
1: /* Person3.cpp */
2: #include<iostream>
3: using namespace std;
5:
6: class Person
7: {
8:
char name[10];
9:
char phone[10];
10:
int age;
11: public:
12:
Person(char* _name, char* _phone, int _age); //생성자함수
13:
void ShowData();
14: };
16: Person::Person(char* _name, char* _phone, int _age)
17: {
18:
strcpy(name, _name);
19:
strcpy(phone, _phone);
20:
age=_age;
21: }
22: void Person::ShowData()
23: {
24: cout<<"name: "<<name<<endl;
25: cout<<"phone: "<<phone<<endl;
26: cout<<"age: "<<age<<endl;
27: }
28:
29: int main()
30: {
31: Person p("Cho", "041-560-1491", 36);
32: p.ShowData();
33: return 0;
34: }
51/97
5.5.3 기본 생성자와 생성자 함수오버로딩
1: class myclass
2: {
3:
int i, j;
4: public:
5:
myclass(){}
6:
void ShowData(){
7:
cout << i << ' ' << j;
8: }

기본 생성자(default constructor)
컴파일러에 의해서 자동으로 삽입된 생
성자를 가리켜 기본 생성자라 한다.

52/97
5.5.3 기본 생성자와 생성자 함수오버로딩
1: /* Default1.cpp */
2: #include <iostream>
3: using namespace std;
4:
5: class myclass
6: {
7:
int i, j;
8: public:
9:
myclass(int a, int b)
10:
{
11:
i = a, j = b;
12:
}
13:
void ShowData(){
14:
cout << i << ' ' << j << endl;
15:
}
16: };
17:
18: int main()
19: {
20: myclass a1(10,20); // 10과 20을 인자로 받는
//생성자 함수 호출
21: a1.ShowData();
22:
23: myclass a2;
// void 생성자 호출
24: a2.ShowData();
25: return 0;
26: }
1: class myclass
2: {
3:
int i, j;
4: public:
5:
myclass() // void 생성자 함수
6:
{
7:
i = j = 0;
8:
}
// 두개의 매개변수를 가지는 생성자 함수
9:
10:
11:
12:
13:
14:
15:
16: };
myclass(int a, int b)
{
i = a, j = b;
}
void ShowData(){
cout << i << ' ' << j << endl;
}
Default1.cpp을 실행시켜보고, 문제점이
있는지 알아보자?
 에러를 수정해 보자.

53/97
5.5.3 기본 생성자와 생성자 함수오버로딩
1: /* Default2.cpp */
2: #include <iostream>
3: using namespace std;
4:
5: class myclass
6: {
7:
int i, j;
8: public:
9:
myclass(int a=0, int b=0)
10:
{
11:
i = a, j = b;
12:
}
13:
void ShowData(){
14:
cout << i << ' ' << j << endl;
15:
}
16: };
17:
18: int main()
19: {
20: myclass a1(10,20); // 10과 20을 인자로 받는 생성자 함수 호출
21: a1.ShowData();
22:
23: myclass a2;
// myclass(0,0) 생성자 함수 호출
24: a2.ShowData();
25:
26:
27:
28:
myclass a3(10); // myclass(10,0) 생성자 함수 호출
a3.ShowData();
return 0;
}

생성자가 지니는 세 가지 특징
첫째: 생성자를 하나도 정의하지 않으면 기
본 생성자가 자동으로 컴파일러에 의하여 삽
입된다.
둘째: 생성자도 함수이므로 오버로딩이 가
능하다.
셋째: 생성자도 함수이므로 디폴트 매개 변
수의 설정이 가능하다.
54/97
5.5.4 소멸자함수의 필요성과 특징
1: /* Person4.cpp */
2: #include<iostream>
3: using namespace std;
4:
5: class Person
6: {
7: char *name;
8: char *phone;
9: int age;
10: public:
11: Person(char* _name, char* _phone, int _age);
12: void ShowData();
13: };
14:
15: Person::Person(char* _name, char* _phone, int _age)
16: {
17: name=new char[strlen(_name)+1];
18: strcpy(name, _name);
19:
20: phone=new char[strlen(_phone)+1];
21: strcpy(phone, _phone); 22:
23: age=_age;
24: }
25: void Person::ShowData()
26: {
27: cout<<"name: "<<name<<endl;
28: cout<<"phone: "<<phone<<endl;
29: cout<<"age: "<<age<<endl;
30: }
31:
32: int main()
33: {
34: Person p("Cho", "041-560-1491", 36);
35: p.ShowData();
36:
37: return 0;
38: }

Preson4.cpp에서는 동적 할당된 메모리 공간을 어디서
도 해제해 주지 않고 있다. -> 메모리 누수 현상 발생

메모리를 자동으로 해제해 주는 함수 필요 -> 소멸자 함
수
55/97
5.5.4 소멸자함수의 필요성과 특징
1: /* Person5.cpp */
2: #include<iostream>
3: using namespace std;
4:
5: class Person
6: {
7: char *name;
8: char *phone;
9: int age;
10: public:
11: Person(char* _name, char* _phone, int
_age);
12: void ShowData();
13: ~Person(); // 소멸자(destructor) 함수
14: };
15:
16: Person::Person(char* _name, char* _phone,
int _age)
17: {
18: name=new char[strlen(_name)+1];
19: strcpy(name, _name);
20:
21: phone=new char[strlen(_phone)+1];
22: strcpy(phone, _phone);
23:
24: age=_age;
25: }
26:
27: void Person::ShowData()
28: {
29: cout<<"name: "<<name<<endl;
30: cout<<"phone: "<<phone<<endl;
31: cout<<"age: "<<age<<endl;
32: }
33:
34: Person::~Person()
35: {
36: delete [] name;
37: delete [] phone;
38: cout << "This is a destructor function" << endl;
39: }
40:
41: int main()
42: {
43: Person p("Cho", "041-560-1491", 36);
44: p.ShowData();
45:
46: return 0; // 리턴과 동시에 p 객체 소멸
47: }
56/97
5.5.4 소멸자함수의 필요성과 특징

C++의 객체 소멸



첫째: 소멸자(destructor) 호출
둘째: 메모리 반환(해제)
소멸자에 대한 외형적 특징




소멸자도 함수이다.
클래스의 이름앞에 ~가 붙은 형태의 함수 이름을
가진다.
리턴하지도 않고, 리턴 타입도 선언되지 않는다.
매개 변수를 받을 수 없다. 따라서 오버로딩은 불가
능하고, 디폴트 매개 변수 선언도 불가능하다.
57/97
5.5.4 소멸자함수의 필요성과 특징
// Destructor.cpp
1: #include<iostream>
2: using namespace std;
3:
4: class myclass {
5:
int a;
6: public:
7:
myclass(); // 생성자 함수
8:
~myclass(); // 소멸자 함수
9:
void show();
10: };
11:
12: myclass::myclass()
13: {
14: cout << "This is a constructor function. \n";
15: }
16:
17: myclass::~myclass()
18: {
19: cout << "This is a destructor function. \n";
20: }
21:
22: void myclass::show()
23: {
24:
cout << "a: " << a;
25: }
26:
27: int main()
28: {
29: myclass a1; // a1 객체 생성 및 생성자 함수 호출
30: myclass a2; // a2 객체 생성 및 생성자 함수 호출
31:
32: return 0; // 리턴과 동시에 객체 a1, a2 소멸 및 소멸자 함수 호출
33: }
실행결과는 다음과 같다.
--------------------------------This is a constructor function.
This is a constructor function.
This is a destructor function.
This is a destructor function.
---------------------------------
58/97
5.5.4 소멸자함수의 필요성과 특징

기본소멸자함수-컴파일러에 의하여 자동적으
로 삽입되는 함수
59/97
[연습문제 5-7]

직사각형을 나타내는 Rectangle 클래스와 원을 나타내는 Circle 클래스를 디자인 해 보자. 이
두 클래스는 넓이를 구하는 기능과 둘레를 구하는 기능(함수)을 가지고 있다. 다음에 제공되
는 main 함수와 출력결과를 통해서 요구되는 Rectangle 클래스와 Circle 클래스를 디자인해
보자.
main 함수의 예
--------------------------------------------------------int main(void)
{
Rectangle rec(3, 4); 초기화로 Rectangle rec(가로(cm), 세로(cm))
cout << "면적: “ << rec.GetArea() << endl;
cout << "둘레: “ << rec.GetRound() << endl;
Circle ring(5); 초기화로 Circle ring(원의 반지름 길이(cm))
cout << "면적: “ << ring.GetArea() << endl;
cout << "둘레: “ << ring.GetRound() << endl;
return 0;
}
--------------------------------------------------------60/97
[연습문제 5-8]

시(hour), 분(minute), 초(second) 정보를 지닐 수 있는 Time 클래스를 정의해 보자. 이 클래스는 멤버 변수
가 지니고 있는 데이터를 적절히 출력하는 기능을 지녀야 한다. 출력 방식은 두 가지로 제공을 한다. 하나는
[시, 분, 초]의 형식을 띄며, 또 하나는 초 단위로 계산한 출력 결과를 보여준다. 제시되는 main 함수와 출력
결과를 참조하세요.
main 함수의 예
--------------------------------------------------------int main(void)
{
Time time1(10); // 10시 0분 0초
Time time2(10, 20); // 10시 20분 0초
Time time3(10, 20, 30); // 10시 20분 30초
time2.ShowTime();
time2.ShowTimeinSec();
return 0;
}
--------------------------------------------------------실행결과
--------------------------------------------------------[10시 20분 0초]
37200 초
--------------------------------------------------------61/97
[연습문제 5-9]

명함 정보를 지닐 수 있는 클래스를 정의해 보자. 클래스의 이름은 NameCard이고
이름, 전화번호, 주소, 직급 정보를 저장할 수 있어야 한다. 생성자 내에서 동적 할
당하고, 소멸자에서 할당받은 메모리를 해제하는 형식으로 구현해 보자.
main 함수
--------------------------------------------------------int main(void)
{
// NameCard Lee(이름, 전화번호, 주소, 직급);
NameCard Lee("Lee Ji Sun", "333-333", "www.ezsun.net", "engineer");
Lee.ShowData();
return 0;
}
--------------------------------------------------------실행결과
------------------------------------------------이 름: Lee Ji Sun
전화번호: 333-3333
주 소: www.ezsun.net
직 급: engineer
------------------------------------------------62/97
5.6 객체지향 프로그래밍의
기본개념
63
5.6.1 클래스를 사용하는 이유

왜 클래스를 사용하는가?

클래스를 사용하면 추상화(abstraction) 및 캡슐화
의 이점 -> 사용자가 정의한 추상적인 데이터형 안에 필요한 데
이터와 그 데이터를 조작하는 함수를 묶어 캡슐화(encapsulation)
시킴으로써 클래스를 사용하는 사용자가 내부 데이터의 형태에
대한 자세한 사항을 알지 않아도 그 데이터형을 사용할 수 있다.

클래스의 상속성의 이점 -> 아무리 잘 정의된 구조체 또
는 클래스라고 하더라도 추가적인 수정사항이나 요구사항이 있을
경우 이전의 클래스를 그대로 사용하면서 정의된 클래스의 변경
없이 요구사항의 변화에 따른 프로그램의 유연성을 얻을 수 있다.
64/97
5.6.2 왜 객체지향 프로그래밍을 배워야할까?

객체지향 프로그래밍은 “객체를 기본 단위로 해서 프로그
램 만들기”라고 할 수 있다.

객체지향 프로그래밍을 사용하면 복잡한 프로그램을 보다 쉽고 빠르
게 만들 수 있다.

일단 만들어진 프로그램을 보수하거나 개선하는데 있어서도 보다 적
은 노력을 필요로 한다
65/97
5.6.3 객체지향 프로그래밍이란?

객체지향 프로그래밍의 비유



규격화된 부품을 조립해서 완제품을 생산하는 공정에 비유할 수 있
다,
자동차 조립과정: 엔진과 타이어와 라이트, 핸들 등이 한 공장에서
모두 만들어지는 것이 아니다. 각 부품들은 자체적인 생산 라인을 통
해서 만들어지며, 최종적으로 한 곳에 모여서 조립되는 것
워드 프로세서(예 HWP.exe)를 프로그래밍 하는 경우: 각각의 기
능은 “객체”가 된다.
66/74
5.6.3 객체지향 프로그래밍이란?
67/48
5.6.4 절차적 언어 방식

절차적 언어에서는 문제를 “해야 할 일의 순서” 로 본다.

관련된 데이터 항목을 레코드 또는 구조체(structure)로 묶고 그 데이
터를 조작하는데 필요한 함수(function) 또는 프로시저(procedure)를
작성한다.

이러한 함수는 데이터와는 별개로 ‘해야 할 일의 순서’에 따라 호출되
며 이때 함수에서는 ‘해야 할 일’에 따라 필요한 데이터를 조작하게된
다.

이러한 과정에서 초점은 어떤 순서로 일을 처리하는가 하는 데 있으며,
중요한 것은 데이터를 조작하는 함수가 된다. 더불어 데이터는 부차적
인 문제가 된다.

프로그램이 존재하는 이유는 데이터 그 자체에 있다.
68/97
5.6.4 절차적 언어방식

예를 들어, 데이터를 처리하는 함수를 쉽게 구현할 수 있도록 전역변
수(global variable)에 저장한다.

전역변수란 함수의 외부에서 선언되어 프로그램 내의 모든 함수에서
마음대로 접근할 수 있도록 되어 있는 변수를 말하며, 프로그램 내의
모든 함수에서 이 변수에 저장된 데이터에 대하여 각기 다른 처리를
할 수 있다.

중요한 데이터를 전역변수에 둔다는 것은 마치 여러 사람들이 드
나드는 호텔과 같은 공공장소의 로비에 중요한 회사 기밀 문서를
놓아두는 것과 같다.

누군가가 그 문서의 내용을 변경시킨다든지 아예 그 문서를 찢어
버릴 수도 있다.
69/97
5.6.4 절차적 언어 방식

이처럼 전역변수에 저장된 데이터는 그 데이터를 변경시키는 일과
는 아무런 상관이 없는 함수에 의해서 망가질 위험이 있다.

그리고, 많은 함수들이 그 데이터에 접근하기 때문에 데이터가 놓
여지는 순서 또한 중요하다.

만약, 데이터의 순서를 변경시키려고 한다면 그와 관련된 모든 함
수를 찾아 일일이 수정해 주어야 한다.
70/97
5.6.4 객체지향 프로그래밍(OOP) 기본개념

Object-Oriented Programming: “객체지향 프로그래밍”,
“개체 중심적인 프로그래밍”

OOP(Object-Oriented Programming) 이란?

추상적인 데이터형(Abstract Data Type)을 정의할 수
있다.

추상적인 데이터형이란 사용자가 정의한 데이터형으로
여기에는 데이터(data)와 그 데이터를 조작하는 함수
(function)을 포함한다.

추상적이란: int, char 또는 float와 같은 내장된 기본적인
데이터형과 구별된다는 것을 말한다.
71/97
5.6.4 객체지향 프로그래밍의 기본개념

OOP(Object-Oriented Programming) 이란?(계속)

OOP는 소프트웨어를 분석, 설계하고 구현하는 많은 방법 중의 한
가지 방법이다.


OOP를 사용한 어플리케이션이 구조적 프로그래밍(Structured
Programming) 기법과 같은 다른 방법을 사용한 어플리케이션
과 외형상 다를 바가 없다.
OOP는 특정언어와 관련이 없다.

C와 같이 OOP를 지원하지 않는 프로그래밍 언어로도 OOP 기
법을 구현하는 일이 전혀 불가능한 것은 아니다.

OOP언어라고 하는 것은 OOP 기법을 쉽게 구현할 수 있도록
여러 가지 기능이 지원되는 언어라는 것을 의미한다.

OOP 기법을 쉽게 구현할 수 있도록 하는 C++ 가 OOP 언어로
불리는 것이며, 특별한 노력을 기울여야 하는 C언어는 OOP 언
어가 될 수 없다.
72/97
5.6.4 OOP 방식의 언어

OOP 언어에서는 문제를 ‘오브젝트(object)’로 본다.

오브젝트(object)는 하나의 실체(entity)로서, 속성(attribute)과 메소드(method:
방법)로 정의된다.

속성이란 다른 오브젝트와 구별되게 하는 내재적인 특징으로 C++에서는 데이터
메버(data member)로 구성된다.

오브젝트의 속성은 그 오브젝트 안에 감추어져 있게 되므로 오브젝트의 외부에서
는 접근할 수 없게 된다.

메소드(method)란 오브젝트가 어떻게 행위(behavior)를 하는가를 나타낸다.

OOP언어에서는 오브젝트가 다른 오브젝트에게 어떠한 행위를 하도록 요청하는
것을 ‘메시지(message)’를 보낸다(Sending message)라고 한다.

다른 오브젝트가 보낸 메시지에 대해 반응하는 행위(behavior)를 메소드(method)
라고 하며, C++에서는 멤버함수(member function)를 정의하여 외부와 인터페이
스(interface)를 하게 된다.
73/97
5.6.4 절차적 언어와 객체지향언어의 비교
74/97
절차적 언어와 객체지향언어의 비교
절차지향 프로그래밍 단점
객체지향 프로그래밍의 장점
규모가 큰 시스템은 하향식 설계가 어렵다.
규모가 커도 상향식 개발이 가능하다.
현실 세계와 소프트웨어 구조가 다르다.
현실 세계의 개념을 프로그래밍에 도입하였다.
변경 사항을 수정하기 어렵다.
개발을 나누어 하기 어렵다.
변경 사항 수정이 용이하다. 즉 유지 보수가 용이
하다.
작업을 분산하여 개발하는 것이 가능하다.
75/97
객체지향 언어에서 사용하는 다양한 용어의 이해

클래스와 객체
76/74
객체지향 언어에서 사용하는 다양한 용어의 이해

클래스와 객체
77/74
객체지향 언어에서 사용하는 다양한 용어의 이해

추상화(Abstraction)


절차적 추상화
데이터 추상화
78/97
OOP 개념: 추상화(Abstraction)




추상화란 자세한 사항은 무시하고, 본질적인 특징에
집중하도록 하는 과정이다.
컴퓨터 또는 프로그래밍 언어 자체에 있는 것보다 더
고급스런 방법으로 정보를 표현하고 해석, 처리하는
것을 말한다.
전통적으로 고급언어(high-level language)라고 하는
모든 프로그래밍 언어는 추상화를 지원한다.
예) 어셈블리어 v.s. C 언어: C로 작성된 프로그램은
컴퓨터가 수행해야 할 작업을 좀 더 추상적으로 표현
하며, 그러한 추상화는 프로그램을 좀 더 명확하고 이
해하기 쉽게 한다.
79/97
OOP 개념: 추상화(Abstraction)


추상화: 절차적 추상화 와 데이터 추상화
절차적 추상화(Procedural Abstraction)



처리과정의 자세한 사항을 무시하는 것을 말한다.
C를 포함한 많은 프로그래밍 언어에서는 여러 단계
의 절차적 추상화 방법을 제공한다.
어셈블리어 형태의 CPU가 처리하는 작업 단위를
나열하는 대신에 프로그래밍 언어가 제공하는 명령
문(statement)을 사용하여 단순화할 수도 있고, 여
기에다 사용자가 정의한 함수(function)를 지원하기
도 한다.
80/97
절차적 추상화(Abstraction) 예
•
두 문자열이 같은지를 검사하는 프로그램
while(*s != ‘0’)
{
if((*s=*t) ||((*s >=‘A’) && (*s <=‘Z’)
&&((*s+32) == *t)) || ((*t >= ‘A’) && (*t
<= ‘Z’) && ((*t +32) == *s)))
{
s++;
t++;
}
else
break;
}
if(*s == ‘0’)
printf(“%s 와 %s는 같다. \n”, s, t);
else%
printf(“%s와 %s는 다르다. \n”, s, t);
if(!stricmp(s,t))
printf(“%s와 %s 는 같다. \n”, s, t);
else
printf(“%s 와 %s는 다르다. \n”, s, t);
81/97
데이터 추상화

데이터 추상화(data abstraction)란 데이터가 어떻게 표현되는가에 대한
자세한 사항을 무시하고 하나의 단위로 처리하는 것을 말한다.

모든 컴퓨터는 데이터를 이진수로 표현한다. C를 포함한 대부분의 프로
그래밍 언어는 정수형을 지원함으로 ’10’이라고 표현하는 것이 ‘0000
0000 0000 1010’라고 표현하는 것보다 편리하다.

C에서는 구조체(structure)와 typedef를 사용하여 사용자가 새로운 데이
터형을 생성할 수 있다.

C에서는 struct를 사용하여 데이터 추상화를 구현하지만, 구조체에 저장
된 데이터를 임의로 조작할 수 있다는 문제점이 있다.

C의 구조체 만으로는 이 구조체와 함께 어떤 함수를 사용해야 하는지를
명확히 알 수 없다.
82/97
캡술화 또는 은닉화(Encapsulation)

은닉화(encapsulation)란 관련된 정보와 그 정보를 처리하는 방법을
하나의 단위로 묶는 것을 말한다.

데이터 추상화와 절차적 추상화 기법을 묶어 하나의 단위로 취급

데이터와 함수를 하나의 단위로 결합하는 행위를 말한다.

함수가 데이터를 감싸고 있어, 데이터를 외부에 대하여 감추어져야
한다.

내부의 저장된 데이터를 외부에 대하여 감춘다는 의미로 ‘데이터 감
추기(Data Hiding)’라고 불리기도 한다.
83/97
은닉화 C 예제 프로그램(1)
#include <stdio.h>
void SetColor(int Color);
int GetColor(void);
void main(void)
{
int Color = 7;
SetColor(Color);
static int color = 0;
void SetColor(int Color)
{
color = Color;
}
int GetColor(void)
{
return color;
}
Color = GetColor();
printf("현재의 색상은 %d이
다. \n", Color);
}
DATA.C – 은닉화를 위한 파일
MAIN.C
84/97
[그림2: C에서의 은닉화의 예]
85/97

DATA.C 파일은 은닉화를 위해 사용되는 파일

static 변수 color는 다른 파일에서 직접 접근할 수 없다.

DATA.C에서 제공하는 함수인 SetColor와 GetColor를 통해서만 static 변수
color에 접근할 수 있다.

DATA.C 파일은 데이터 감추기(data hiding)을 지원하게 된다.

문제점: static 변수 color에는 반드시 하나의 값만을 저장하게 된다. 가령 배경과
전경 두 색상을 사용한다고 하자.

이때 두 색상을 표현하기 위해 반드시 두개의 static 변수(예를 들어 BackgroundColor
와 ForegroundColor)를 갖고 있어야 하며, 이들 변수에 접근하기 위한 함수도 두개씩
(GetBackgroundColor 와 GetForegroundColor와 SetBackgroundColor 와
SetForegroundColor) 작성해야 한다. 이들 함수는 비슷한 코드를 가지고 있기 때문에
매우 비효율적이다. 이것을 피하기 위해 switch문을 사용하면,
86/97
은닉화 예제 C 프로그램 (2)
void SetColor(int sort, int Color)
{
switch(sort)
int GetColor(int sort)
{
switch(sort)
{
{
case 1: // 배경색상
case 1: // 배경색상
BackgroundColor = Color;
return BackgroundColor;
break;
case 2: // 전경색상
case 2: // 전경색상
return ForgroundColor;
ForgroundColor = Color;
break;
}
}
}
}
87/97

만약 여러 종류의 색상이 필요하다면, 그 때마다 사용하든
하지 않든 새로운 변수를 정의해야 하며, 또한 switch 문에
새로운 경우를 추가해야 한다.

즉, C에서의 은닉화 방법은 오브젝트(object)를 지원하지
못한다.

OOP의 클래스(class)는 이러한 단점을 극복하는 강력한
추상화와 은닉화 기법을 제공한다.
88/97
은닉화 관련 C++ 예제 프로그램
#include <iostream.h>
class Color
{
private:
int color;
public:
void Color::SetColor(int colorValue);
int Color::GetColor(void);
};
int main(void)
{
Color BackgroundColor, ForgroundColor;
int returnColor;
BackgroundColor.SetColor(7);
returnColor = BackgroundColor.GetColor();
cout<<“배경색상은” << returnColor<<“이
다.\n”;
void Color::SetColor(int ColorValue)
{
color = ColorValue;
}
int Color::GetColor(void)
{
return color;
}
ForegroundColor.SetColor(4);
returnColor=ForgroundColor.SetColor(4);
cout<<“전경색상은”<<returnColor<<“이다.\n”;
}
89/97
다형성(Polymorphism)



다형성: 하나 이상의 형태를 띠는 것
OOP에서 다형성이란 ‘같은 메시지에 대하여 다른 행
동을 하는 것’을 의미
예를 들어, 두 개의 수를 더한다고 하자.



이때 ‘더한다’라고 하는 메시지에 대하여 x 와 y가 여러가지 데
이터형이 될 수 있다. X와 y가 정수형이면 ‘더한다’라는 메시지
는 정수 값을 반환해 주고, 복소수 이면 복소수값을 반환해 준
다. 또한 x와 y가 문자열이면 ‘더한다’라는 메시지는 두 문자열
을 연결하는 의미가 될 수도 있다.
다형성이란 같은 메시지에 대하여 오브젝트가 서로
다른 행동을 하는 것을 말한다.
C++에서 다형성은 가상함수(virtual function)을 통해
구현된다. 또는 함수오버로딩, 연산자 오버로딩
90/97
다형성(Polymorphism)

다형성
91/97
상속성(Inheritance)

각각의 오브젝트는 하나 이상의 다른 오브젝트들과 관련을 맺고 있다.

새로운 오브젝트를 정의할 때 이미 있는 오브젝트와 관련성을 갖게 된다.

상속성이라는 용어는 새로운 클래스가 다른 클래스에서 데이터와 함수를
상속받아 여기에 좀 더 특별한 특징을 가지도록 할 수 있다는 데서 생겨났
다.

C++에서는 다른 클래스에 상속해 주는 클래스를 상위클래스(parent
class) 또는 기초 클래스(base class)라고 하고, 상속받는 클래스를 ‘하위
클래스(child class)’ 또는 ‘파생 클래스(derived class)’라고 한다.

실제 오브젝트는 하나 이상의 오브젝트에서 특징을 상속받게 된다. -> 다
중상속(multiple inheritance)

C++에서는 다중상속을 지원한다.
92/97
그림 3: 상속성의 예
93/97
5.7 프로그래밍 실습문제
94
[실습 문제 5-1]
실수부와 허수부로 되어 있는 복소수를 표현하고, 사칙연산이 가능한 Complex 클래스를
정의하고, 그 사용 예를 보여라.
Complex 클래스 정의 시 다음과 같은 특징을 고려하여 설계하세요.

생성자 함수에서는 실수부와 허수부를 초기화하라.
예) Complex a(1,2); // a = 1+2i로 객체 생성과 더불어 초기화

복소수 12.4 + 15.6i를 Console 화면에 출력할 수 있는 기능을 포함하여야 하며,
Complex 클래스의 public 함수인 Display() 함수를 이용하여, Console 화면에 복소
수를 출력하는 기능을 포함하라

복소수 사칙연산 기능 포함
예를 들어, 두 복소수 x = x1+y1i, y= x2+y2i 일 경우
add(z=x+y): z = (x1+x2) + (y1+y2)i
subtract(z=x-y): z = (x1-x2) +(y1-y2)i
multiply(z=x*y): z = (x1*x2 - y1*y2)+(x1*y2+y1*x2)i
divide(z=x/y): z = (x1*x2+y1+y2)/(x2^2 + y2^2) + (y1*x2-x1*y2)i/(x2^2+y2^2)

실수부와 허수부 값을 설정하고, 반환하는 함수 SetRe(), SetIm(), GetRe(), GetIm()
기능 포함
95/97
[실습 문제 5-2]
다음의 성질을 갖는 Car 클래스를 구현해보자. 자동차는 연비값( Km/L 로 측정)과 연료통
의 연료 양 값을 가진다. (연비값: double efficiency, 연료통의 연료 양: double gas).
연비는 생성자함수에 명시되어 초기화된다. 초기 연료 양은 0으로 한다. Car 클래스는
다음과 같은 멤버함수를 포함할 수 있도록 디자인 해보자.
- 얼마의 거리를 달리면 연료통의 연료 양이 줄어들게 하는 시뮬레이션을 실행하는 멤버함
수 drive
- 현재의 연료 양을 반환하는 함수, get_gas
- 자동차의 연료통을 가득 채우는 함수, add_up
main 함수에서 Car 클래스의 사용 예를 보이면 다음과 같다.
Car Sorento(15); // Sorento 객체를 생성한다. Sorento 차의 연비는 15 Km per 1
Sorento.add_gas(65); // 연료를 65 주유한다.
Sorento.drive(100); // 100 Km 주행한다.
cout << Sorento.get_gas() << endl; // 남아 있는 현재 연료 양을 출력한다.
Sorento.add_up(); // 연료통을 가득채운다.
cout << Sorento.get_gas() << endl; // 현재 연료통의 연료 양을 출력한다.
96/97
질문 & 답변
Thank You !
수고하셨습니다.
97/97