학습 개요
- 객체 지향 프로그래밍의 기본적 개념을 바탕으로 클래스를 선언하고 객체를 정의하여 사용하는 기본적인 구문에 대하여 학습함
- 클래스 선언문의 기본 형식과 클래스를 선언하기 위해 소스 파일을 구성하는 방법 등 프로그램 작성을 위한 기본적인 사항을 다룸
- 생성자와 소멸자를 이용하여 객체가 생성될 때와 소멸될 때 처리해야 할 작업이 자동적으로 이루어지도록 프로그램을 작성하는 방법을 학습함
학습 목표
- 데이터 멤버와 멤버 함수로 구성되는 클래스를 선언할 수 있음
- 클래스 선언을 위해 필요한 소스 파일을 만들어 프로젝트를 구성할 수 있음
- 생성자를 이용하여 객체 생성과 함께 초기화되도록 클래스를 선언할 수 있음
- 소멸자를 이용하여 객체 소멸 과정에서 필요한 정리 작업을 수행할 수 있도록 클래스를 선언할 수 있음
주요 용어
- 클래스(class)
- 프로그램이 표현하고자 하는 대상(객체)이 어떠한 속성(데이터 멤버)을 저장하고 있어야 하고, 어떤 행위(멤버 함수)을 할 수 있는 가를 선언한 것
- 객체(object)
- 클래스의 실제 사례(instance)에 해당되며, 고유한 속성 값(데이터 멤버의 값)을 가지며, 이를 바탕으로 클래스에 정의된 행위를 할 수 있음
- 캡슐화(encapsulation)
- 객체 내부의 상세한 구현 부분과 사용자의 관점을 분리하는 것을 나타냄
- 사용자는 객체의 내부 요소를 직접 사용할 수 없으며, 공개된 인터페이스를 통해 객체를 사용함
- 생성자(constructor)
- 객체가 생성될 때 수행할 작업을 정의하는 특수한 멤버 함수로, 객체의 초기화 작업을 수행함
- 소멸자(destructor)
- 객체가 소멸될 때 수행할 작업을 정의하는 특수한 멤버 함수로, 객체가 가지고 있는 자원을 반납하는 등의 처리를 담당함
강의록
클래스 선언과 객체 정의
객체
- 객체(object)란?
- 소프트웨어 시스템 안의 어떠한 대상을 표현한 것으로
- 정해진 처리를 수행할 수 있음
- 행위, 메소드, 멤버 함수
- 처리 과정에 따라 내부 상태가 변화할 수 있음
- 속성, 데이터 멤버
- 다른 객체와 상호 작용 할 수 있음
- 메시지 전달(멤버 함수 호출)
- 정해진 처리를 수행할 수 있음
- 소프트웨어 시스템 안의 어떠한 대상을 표현한 것으로
클래스
- 클래스(class)란?
- 객체의 설계도
- 객체가 포함할 데이터 멤버의 선언과 멤버 함수의 정의를 포함함
클래스 선언
클래스 선언문의 형식
1 2 3 4 5 6 7 8
class ClassName { 가시성_지시어_1: 데이터 멤버 선언; 멤버함수 선언; // 원형 선언 또는 멤버 함수 정의 가시성_지시어_2: 데이터 멤버 선언; 멤버함수 선언; // 원형 선언 또는 멤버 함수 정의 };
- 가시성 지시어
- 클래스의 멤버가 공개되는 범위를 나타냄
- 종류
private
,public
,protected
공개 범위
가시성 지시어 공개 범위 private
(디폴트)소속 클래스의 멤버 함수 친구 클래스의 멤버 함수 및 친구 함수 그 외의 범위에는 비공개 public
전 범위 용도
가시성 지시어 용도 private
(디폴트)정보 은닉을 위해 사용됨 클래스의 구현을 위한 내부 상태(데이터 멤버)는 일반적으로 private
으로 지정함public
주로 외부에 제공할 인터페이스를 공개하기 위해 사용됨
- 캡슐화(encapsulation)
객체 내부의 상세한 구현 부분과 외부 사용자의 관점을 분리함
- 내부 속성 등 구현에 대한 부분은 공개하지 않으며(정보 은닉), 객체 외부에서는 공개된 인터페이스를 통해 객체를 사용할 수 있음
클래스의 예 - Counter
클래스
Counter
클래스- 계수기를 나타내는 클래스를 선언하라.
- 계수기 객체는 값을 0으로 지울 수 있고, 값을 1씩 증가 시킬 수 있으며, 현재의 계수기 값을 알려줄 수 있다.
행위
멤버함수 비고 void reset()
계수기의 값을 0으로 지움 void count()
계수기의 값을 +1 증가 시킴 int getValue()
계수기의 현재 값을 알려 줌 속성
Counter -value: int +reset(): void +count(): void +getValue(): int
Counter 클래스의 선언 - Counter.h
1
2
3
4
5
6
7
8
9
10
#ifndef COUNTER_H_INCLUDED
#define COUNTER_H_INCLUDED
class Counter { // 클래스 Counter의 선언 시작
/**
* Counter의 멤버 선언
**/
};
#endif // COUNTER_H_INCLUDED
객체의 정의 및 사용
객체 정의 형식
1 2
ClassName objName; ClassName objName1, objName2, ······;
ex)
1 2 3 4
int main() { Counter c1, c2; }
객체 사용 형식
- 객체 이름에 멤버 선택 연산자(.)를 사용하여 객체의 멤버를 액세스함
1 2
cin >> objName.dataMember; objName.memFunc( );
- 객체의 멤버 함수 안에서 그 객체에 속한 멤버를 사용할 때는 멤버 이름만으로 액세스함
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13
class Counter { int value; public: void reset() { value = 0; } void count() { ++value; } int getValue() const { return value; } };
1 2 3 4 5
int main() { Counter c; c.reset(); c.count(); }
Counter 객체의 정의 및 사용 - CntMain.cpp
private
멤버 접근하기 때문에 오류 발생1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <iostream> #include "Counter.h" using namespace std; int main() { Counter cnt; // Counter 객체의 정의 cnt.value = 0; // 계수기를 0으로 지움 cout << "계수기의 현재 값 : " << cnt.value << endl; cnt.value++; // 계수기를 1 증가시킴 cnt.value++; cout << "계수기의 현재 값 : " << cnt.value << endl; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13
class Counter { int value; public: void reset() { value = 0; } void count() { ++value; } int getValue() const { return value; } };
올바른 사용 법
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <iostream> #include "Counter.h" using namespace std; int main() { Counter cnt; // Counter 객체의 정의 cnt.reset(); // 계수기를 0으로 지움 cout << "계수기의 현재 값 : " << cnt.getValue() << endl; cnt.count(); // 계수기를 1 증가시킴 cnt.count(); cout << "계수기의 현재 값 : " << cnt.getValue() << endl; return 0; }
cnt:Counter -value ? cnt:Counter -value 0 cnt:Counter -value 1 cnt:Counter -value 2
const
멤버 함수
- 데이터 멤버의 값을 수정하지 않는 멤버 함수
Counter.h
1 2 3 4 5 6 7 8 9 10 11 12
class Counter { int value; public: void reset() { value = 0; } void count() { ++value; } int getValue() const { return value; } };
1 2 3
const Counter c; int n = c.getValue(); // OK! c.count(); // 오류
Counter.h
1 2 3 4 5 6 7 8 9 10 11 12
class Counter { int value; public: void reset() { value = 0; } void count() { ++value; } int getValue() { return value; } };
1 2 3 4 5
void f(Counter& c) { c.count(); cout << c.getValue(); }
오류
1 2 3 4
void g(const Counter& c) { cout << c.getValue(); }
Counter.h
1 2 3 4 5 6 7 8 9 10 11 12
class Counter { int value; public: void reset() { value = 0; } void count() { ++value; } int getValue() const { return value; } };
1 2 3 4 5
void f(Counter& c) { c.count(); cout << c.getValue(); }
1 2 3 4 5
void g(const Counter& c) { cout << c.getValue(); }
소스 파일의 구성
생성자
생성자
- 생성자(constructor)
- 객체가 생성될 때 수행할 작업을 정의하는 특수한 멤버 함수
- 생성자에 인수를 전달할 수 있도록 매개 변수를 선언할 수 있음
- 생성자를 여러 개 다중정의할 수 있음
- 생성자의 특성
- 클래스의 이름을 사용하여 선언함
- 생성자 머리에 반환 자료형을 표시하지 않으며,
return
명령으로 값을 반환할 수 없음 - 생성자를
public
으로 선언해야 클래스 외부에서 객체를 생성할 수 있음
생성자 선언 형식
1 2 3 4 5 6 7 8
class ClassName { public: // 생성자 ClassName(fParameterList){ // 객체 생성을 위한 준비 작업 } };
생성자의 예 - Counter
클래스
Counter.h (생성자 없는 버전)
1 2 3 4 5 6 7 8 9 10 11 12 13
class Counter { int value; public: void reset() { value = 0; } void count() { ++value; } int getValue() const { return value; } };
CntMain.cpp
1 2 3 4 5 6 7 8 9 10 11
int main() { Counter cnt; cnt.reset(); cout << "계수기의 현재 값 : " << cnt.getValue() << endl; cnt.count(); cnt.count(); cout << "계수기의 현재 값 : " << cnt.getValue() << endl; return 0; }
cnt:Counter -value 0
Counter.h (생성자 있는 버전)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Counter { int value; public: Counter() { value = 0; } void reset() { value = 0; } void count() { ++value; } int getValue() const { return value; } };
CntMain.cpp
1 2 3 4 5 6 7 8 9 10
int main() { Counter cnt; // cnt.reset(); cout << "계수기의 현재 값 : " << cnt.getValue() << endl; cnt.count(); cnt.count(); cout << "계수기의 현재 값 : " << cnt.getValue() << endl; return 0; }
cnt:Counter -value 0
초기화 리스트
- 초기화 리스트
- 생성자의 머리에 데이터 멤버를 초기화하는 값들을 나열한 리스트
데이터멤버이름{초깃값}
형태로 초깃 값을 지정
Counter.h
1 2 3 4 5
class Counter { int value; public: Counter() : value{0} { } // 생성자 };
소멸자
소멸자
- 소멸자(destructor)
- 객체가 소멸될 때 수행할 작업을 정의하는 특수한 멤버 함수
- 소멸자의 특성
- 클래스의 이름에
~
를 붙여 선언함 - 소멸자 머리에 반환 자료형을 표시하지 않으며,
return
명령으로 값을 반환할 수 없음 - 매개 변수가 없으며, 클래스에 하나의 소멸자만 정의할 수 있음
public
으로 선언하는 것이 일반적임- 상속을 통해 파생 클래스를 정의하는 경우
virtual
을 지정하여 가상 함수가 되도록 하는 것이 좋음
- 클래스의 이름에
소멸자 선언 형식
1 2 3 4 5 6 7 8 9 10 11
class ClassName { public: ClassName(fParameterList) { // 생성자 // 객체 생성을 위한 준비 작업 } ~ClassName() { // 소멸자 // 객체 제거를 위한 정리 작업 } };
Person
클래스의 명세
Person
클래스- 사람을 나타내는 클래스를 선언하고자 한다. 사람 객체는 ‘···에 사는 ···입니다.’라고 자신을 알릴 수 있으며, 주소를 변경할 수 있다.
행위
멤버 함수 비고 Person(char* name, char* addr)
생성자 ~Person()
소멸자 void print()
‘···에 사는 ···입니다’ 라고 출력함 void chAddr(char* newAddr)
주소를 변경함 속성
데이터 멤버 비고 char* name
이름을 저장함 char* addr
주소를 저장함
Person 클래스의 선언 - Person.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef PERSON_H_INCLUDED
#define PERSON_H_INCLUDED
class Person { // 클래스 Person의 선언 시작
char* name; // 이름을 저장하는 데이터멤버
char* addr; // 주소를 저장하는 데이터멤버
public: // public 멤버함수
Person(const char* name, const char* addr); // 생성자
~Person(); // 소멸자
void print() const; // 이름과 주소 출력
void chAddr(const char* newAddr); // 주소 변경
};
#endif // PERSON_H_INCLUDED
Person 클래스의 선언 - Person.cpp
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
#include <iostream>
#include <cstring>
#include "Person.h"
using namespace std;
Person::Person(const char* name, const char* addr)
{
// 이름을 저장할 공간 할당
this -> name = new char[strlen(name) + 1];
// 데이터 멤버 name에 이름을 복사
strcpy(this -> name, name);
// 주소를 저장할 공간 할당
this ->addr = new char[strlen(addr) + 1];
// 데이터 멤버 addr에 주소를 복사
strcpy(this -> addr, addr);
cout << "Person 객체 생성함(" << name << ")" << endl;
}
Person::~Person() // 소멸자
{
cout << "Person 객체 제거함(" << name << ")" << endl;
delete[] name; // 이름 저장공간 반납
delete[] addr; // 주소 저장공간 반납
}
void Person::print() const
{
cout << addr << "에 사는 " << name << "입니다." << endl;
}
void Person::chAddr(const char* newAddr)
{
delete[] addr; // 기존 공간 반납
// 새로운 주소에 맞는 공간 할당
addr = new char[strlen(newAddr) + 1];
strcpy(addr, newAddr); // 데이터멤버 addr에 새로운 주소를 복사
}
Person 클래스의 선언 - PrsnMain.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include "Person.h"
using namespace std;
int main()
{
Person* p1 = new Person("이철수", "서울시 종로구");
Person* p2 = new Person("박은미", "강원도 동해시");
p1->print();
p2->print();
cout << endl << "주소 변경 : ";
p2->chAddr("대전시 서구");
p2->print();
delete p1;
delete p2;
return 0;
}
출력 화면
1 2 3 4 5 6 7 8
Person 객체 생성함(이철수) Person 객체 생성함(박은미) 서울시 종로구에 사는 이철수입니다. 강원도 동해시에 사는 박은미입니다. 주소 변경 : 대전시 서구에 사는 박은미입니다. Person 객체 제거함(이철수) Person 객체 제거함(박은미)
연습 문제
다음 중 클래스 선언문에서 정보 은닉을 위해 사용되는 가시성 지시어는?
a.
private
- 클래스의 구현을 위한 내부 상태인 데이터 멤버는 일반적으로
private
으로 지정하며,정보 은닉을 위해 사용됨 - 외부에 제공할 인터페이스로 공개하기 위해서는
public
으로 지정함
- 클래스의 구현을 위한 내부 상태인 데이터 멤버는 일반적으로
위 지문의 클래스 선언문에서 멤버 함수
memF1()
의 몸체 (가)에서 사용할 수 있는 문장은?1 2 3 4 5 6 7 8
class ClassA { int a, b; public: int memF1() const { // (가) } };
a.
return a * b;
- 멤버 함수
memF1()
은const
멤버 함수로 선언되었으므로, 함수 내에서 데이터 멤버 a나 b에 대해서는 값을 읽을 수만 있고 값을 변경하는 문장은 사용할 수 없음
- 멤버 함수
위 지문의 클래스 선언문에서
const
키워드를 넣는 것이 바람직한 곳을 모두 나열한 것은?1 2 3 4 5 6 7 8
class Counter { int value; public: Counter() // ___(ㄱ)___ {value = 0;} void reset() // ___(ㄴ)___ {value = 0;} void count() // ___(ㄷ)___ {++value;} int getValue() // ___(ㄹ)___ {return value;} };
a. ㄹ
- 데이터 멤버의 값을 수정하지 않는 멤버 함수에 대하여
const
를 지정함
- 데이터 멤버의 값을 수정하지 않는 멤버 함수에 대하여
위 지문의 클래스에서 객체가 생성될 때 데이터 멤버 x가 0으로 초기화되도록 공란에 생성자를 선언한 것으로 적절한 것은?
1 2 3 4 5 6
class ClassB { int x; public: // ______ };
a.
ClassB() : x{0} { }
- 생성자는 클래스의 이름과 같고 결과 값을 반환하지 않으며, 이러한 경우 일반 함수에서는 함수의 머리 부에 반환 자료형을
void
로 표기하나, 생성자의 경우는 이마저도 표기하지 않음 - 함수의 몸체에서는 x에 0을 대입하는 문장을 사용하거나, 초기화 리스트를 이용하여 x를 초기화함
- 생성자는 클래스의 이름과 같고 결과 값을 반환하지 않으며, 이러한 경우 일반 함수에서는 함수의 머리 부에 반환 자료형을
위 지문은 ClassA의 선언문 일부이다. 소멸자의 머리부 ㈀에 넣을 적절한 내용은?
1 2 3 4 5 6 7 8
class ClassA { int x; public: // __(ㄱ)__ { } };
a.
~ClassA()
- 소멸자는 클래스의 이름에
~
를 붙인 이름을 사용하며, 인수를 전달 받을 수 없음 - 또한
return
명령으로 값을 반환 할 수 없으며, 일반 함수처럼void
라고 표기하지도 않음
- 소멸자는 클래스의 이름에
정리 하기
- 클래스는 프로그램이 표현하고자 하는 대상(객체)이 어떠한 속성(데이터 멤버)를 저장하고 있어야 하고, 어떤 행위(멤버 함수)를 할 수 있는 가를 선언한 것임
- 클래스에 해당 되는 실제 사례(instance)를 객체(object)라고 함
- 객체는 고유한 속성 값(데이터 멤버의 값)을 가지며, 이를 바탕으로 클래스에 정의 된 행위를 할 수 있음
- 가시성 지시어
private
,public
,protected
는 클래스의 멤버가 공개 되는 범위를 지정하기 위해 사용 되는데, 정보 은닉을 위해private
을, 외부에 제공할 인터페이스를 공개하기 위해public
을 사용함 - 클래스에서 데이터 멤버의 값을 변경하지 않는 멤버 함수는
const
멤버 함수로 정의함 - 생성자는 객체가 생성 될 때 수행하는 작업을 정의하는 특수한 멤버 함수로서, 클래스 이름과 동일한 이름으로 선언하며, 일반적으로 객체를 초기화 하는 작업을 수행함
- 소멸자는 객체가 소멸 될 때 수행할 작업을 정의하는 특수한 멤버 함수로, 클래스 이름과 동일한 이름 앞에
~
를 붙여 선언하며, 객체가 가지고 있는 자원을 반납하는 등의 처리를 담당함