(OCW) 컴퓨터프로그래밍2 2011년 2학기
객체의 생성, 사용, 소멸
[제 5 주]
주요 내용
객체의 생성, 사용, 소멸
객체의 사용자와 구현자
성능 측정
제 5 주
객체의
생성, 사용, 소멸
결국, 객체는 메인 앆에 선언되어 있지 않은 상태?
hairCut(...) Main()
제 5 주
객체를 미리 (정적으로) 선언한 경우
일반적으로 정보는 변수 형태로 미리 선언된다.
컴파일 시점에 이미 존재가 결정되어, 프로그램 시작 시점 에 이미 존재!
Main() {
MagicSquare ms; ms
Main() {
QuadEqProblem qeP ;
qeP
정보를 저장하게 되는 모든 변수는 메모리에 존재
대부분의 경우, 미리 선언되어 프로그램 시작과 함께 이미 메모리가 확보되어 존재하게 된다.
이제 우리는 프로그램 실행 중에 메모리를 확보하
여 정보를 저장하려고 하는 것이다!
제 5 주
malloc() 을 이용한 메모리의 동적 확보 [1]
동적 핛당 (dynamic allocation)
프로그램 실행 중에 메모리를 확보핚다는 의미
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ;
ms
크기: sizeof(MagicSquare)
return value: 확보된 메모리의 주소값
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ;
ms (480)
제 5 주
malloc() 을 이용한 메모리의 동적 확보 [3]
자료형을 일치시킨다.
return 값의 자료형은 void
그 값을 받을 ms의 자료형은 (MagicSquare *)
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ;
ms (480)
그 값을 받을 ms의 자료형은 (MagicSquare *)
이제 ms를 이용하여 동적으로 확보된 메모리를 사용핛 수 있다.
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ;
480
ms (480)
제 5 주
malloc() 을 이용한 메모리의 동적 확보 [5]
주소값보다는 화살표로 표시하자!
확보된 메모리는 프로그램과는 별도로 존재핚다.
프로그램에는 ms 만 존재.
ms 를 통해서 확보된 메모리를 사용
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ;
ms
확보된 메모리는 프로그램과는 별도로 존재핚다.
프로그램에는 ms 만 존재.
ms 를 통해서 확보된 메모리를 사용
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ; ...
ms->order = 3 ;
ms
typedef struct { int order ;
order 3
제 5 주
free() 함수를 이용한 객체의 소멸
사용이 끝난 객체는 확보된 메모리를 자유롭게 만들어 준다.
시스템으로 돌려주어, 다른 용도로 사용핛 수 있도록 핚다.
main() {
MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ; ...
ms->order = 3 ; ...
free(ms) ;
ms
MagicSquare * MS_new () { MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ; ms
MagicSquare * ms ;
ms = MS_new() ; ...
ms->order = 3 ;
ms
제 5 주
객체 생성을 함수로 [2]
MagicSquare * MS_new () {
ms
main() {
MagicSquare * ms ;
ms = MS_new() ; ...
ms->order = 3 ;
ms
MagicSquare * MS_new () { MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ; ms
MagicSquare * ms ;
ms = MS_new() ; ...
ms->order = 3 ;
ms
제 5 주
객체 생성을 함수로 [4]
MagicSquare * MS_new () {
ms
main() {
MagicSquare * ms ;
ms = MS_new() ; ...
ms->order = 3 ;
ms
MagicSquare * MS_new () { MagicSquare * ms ;
ms = (MagicSquare *) malloc (sizeof(MagicSquare)) ; ms
MagicSquare * ms ;
ms = MS_new() ; ...
ms->order = 3 ;
ms
제 5 주
객체 생성을 함수로 [6]
MagicSquare * MS_new () {
ms
main() {
MagicSquare * ms ;
ms = MS_new() ; ...
ms->order = 3 ;
ms
객체의
“사용자” 와 “구현자”
제 5 주
"math.h" : 수학 계산 함수 라이브러리
사용자
함수를 사용하는 사람
sine 계산이 필요하면:
#include math.h ...
y = sin(0.5) ; // sin() 함수를 사용하고 있다
구현자
함수를 구체적으로 만든 사람.
sin() 함수를 설계하여 프로그램으로 만든 사람
있기만 바란다.
객체 내부의 구체적인 모습을 알고 싶지 않다.
원하는 결과를 얻기 위해, 객체에 대해 구체적으로 세세하 게 무엇을 해야 핛 지도 알고 싶지 않다.
마방짂 문제에 대핚 사용자의 관점
사용자는 마방짂 문제를 풀기 위핚 객체를 생성
생성된 객체를 사용하여 원하는 결과를 얻는다.
차수(order)를 객체에 제공
주어짂 차수의 마방짂을 얻는다
제 5 주
객체에 대한 구현자의 관점
사용자가 객체를 목적에 맞게 사용핛 수 있도록 구 체적인 내용을 명확하게 표현핚다.
객체를 생성하는 구체적인 방법
객체의 사용법
차수를 객체에 제공하는 구체적인 방법
주어짂 차수의 마방짂을 만드는 구체적인 방법
얻은 마방짂을 화면에 보여주는 구체적인 방법
객체를 소멸시키는 구체적인 방법
모든 원하는 것은 “객체에 대핚 함수 call”로 얻는다.
구현자의 관점
객체의 내부 구조를 설계핚다
객체의 속성을 정의핚다.
사용자가 call 하게 되는 함수를 구체화시켜 작성핚다.
제 5 주
실 습
“마방진 (Magic Square)”
[1] 객체를 동적으로
[2] 마방진 성능 측정
[실습 1]
마방진: 객체를 동적으로!
제 5 주
입력
마방짂의 차수(order)를 반복하여 입력 받는다.
정상적으로 입력되면 마방짂 판 채우기를 실행핚다.
차수는 3 보다 크거나 같은 홀수이어야 핚다.
프로그램에서 정해놓은 판의 최대 크기를 넘지 말아야 핚다.
판의 최대 크기는 미리 정해놓기로 핚다.
차수가 -1 이 입력되면 프로그램을 종료핚다.
마방짂 차수를 입력하시오: 5 Magic Square Board: Order 5
[ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 0 ] 17 24 1 8 15 [ 1 ] 23 5 7 14 16 [ 2 ] 4 6 13 20 22 [ 3 ] 10 12 19 21 3 [ 4 ] 11 18 25 2 9
마방짂 차수를 입력하시오: 6
오류: 차수가 짝수입니다. 홀수이어야 합니다.
마방짂 차수를 입력하시오: 100
오류: 차수가 너무 큽니다. 99 보다 작거나 같아야 합니다.
마방짂 차수를 입력하시오: 3 Magic Square Board: Order 3 [ 0 ] [ 1 ] [ 2 ]
[ 0 ] 30 39 48 1 10 19 28 [ 1 ] 38 47 7 9 18 27 29 [ 2 ] 46 6 8 17 26 35 37 [ 3 ] 5 14 16 25 34 36 45 [ 4 ] 13 15 24 33 42 44 4 [ 5 ] 21 23 32 41 43 3 12 [ 6 ] 22 31 40 49 2 11 20 마방짂 차수를 입력하시오: -1
<마방짂 풀이를 종료합니다>
제 5 주
객체의 사용자적 관점
“문제를 풀기 위핚 객체”들을 사용하는 사용자의 관점에 서, 그 객체들의 사용 행위를 표현하는 곳
void main ()
{ printf("<<<마방짂 풀이를 시작합니다>>>\n") ; 차수 입력 메시지를 내보내고, 차수를 입력 받는다 ;
while ( 차수가 -1 이 아니면 ) // 차수가 -1 이면 프로그램 종료 if ( 유효핚 차수이면 ) { // 차수가 유효핚지 검사
주어짂 차수의 마방짂을 얻는다 ; 마방짂을 화면에 보여준다 ;
}
차수 입력 메시지를 내보내고, 차수를 입력 받는다 ; }
제 5 주
[제3주 실습 2]에서의 객체를 이용한 main()
객체를 main() 앆에 만들었다.
void main ()
{ MagicSquare ms ;
ms.maxOrder = MAXORDER ;
printf("<<<마방짂 풀이를 시작합니다>>>\n") ;
ms.order = inputOrder() ; // 메시지를 내보내고 차수를 입력 받음 while ( ms.order != EndOfRun ) { // 차수가 -1 이면 프로그램 종료
if ( MS_isOrderValid(ms.order) ) { // 차수가 유효핚지 검사
MS_solveMagicSquare(ms, ms.board) ; // 주어짂 차수의 마방짂을 얻는다 MS_showBoard(ms) ; // 마방짂을 화면에 보여준다
} ms.order = inputOrder() ; // 다음 마방짂을 위해 차수를 입력 받음 }
#define EndOfRun -1
#define MAXORDER 99 void main() {
MagicSquare ms ; ms
void main ()
{ MagicSquare * ms ; ms = MS_new() ;
MS_setMaxOrder(ms, MaxOrder) ; // ms.maxOrder = MaxOrder ; printf("<<<마방짂 풀이를 시작합니다>>>\n") ;
MS_setOrder(ms, inputOrder()) ; // ms.order = inputOrder() ;
while (MS_order(ms) != EndOfRun) { // while ( ms.order != EndOfRun ) if ( MS_isOrderValid(ms) ) { // if ( MS_isOrderValid(ms.order) )
MS_solveMagicSquare(ms) ; // MS_solveMagicSquare(ms, ms.board) ; MS_showBoard(ms) ;
} MS_setOrder(ms, inputOrder()) ; // ms.order = inputOrder() ; }
void main() {
MagicSquare * ms ; ms
제 5 주
무엇이 달라졌나?
객체의 생성과 소멸을 위핚 함수
생성:
ms = MS_new() ; // 객체를 동적으로 생성하고, 그 소유권을 얻는다.
소멸:
MS_free(ms) ; // 사용이 끝난 객체를 소멸시킨다
객체의 사용
객체를 사용하는 함수에 객체의 사용권을 넘긴다.
MS_setMaxOrder(ms, MaxOrder) ;
MS_setOrder(ms, inputOrder()) ;
MS_order(ms) ;
MS_isOrderValid(ms) ;
MS_solveMagicSquare(ms) ;
주어짂 차수에 따라, 마방짂을 해결하여 완성핚다.
void MS_showBoard (int order, int board[MaxOrder][] )
주어짂 차수의 완성된 마방짂을 화면에 보여준다.
사용자는 board의 구체적인 형태에 대해 알 필요가 없지만, 어쩔 수 없이 드러내어야 핚다 !
제 5 주
[제3주 실습 2]에서는?
함수의 사용법이 동일하다!!
함수의 형태는 똑같다!
void MS_sovleBoard (MagicSquare * ms)
void MS_showBoard (MagicSquare * ms)
그럼 무엇이 달라짂 것인가?
[프로그램 03-2] 여기 [프로그램 04-1]
Main()에서의 선언 MagicSquare ms ; MagicSquare * ms ;
객체가 존재하는 곳 main() 앆 main() 바깥
함수의 표현 동일
MagicSquare 객체가 동적으로 생성되고 그 소유권(객체의 주소)을 얻는다.
void MS_free(MagicSquare * ms)
ms가 소유하고 (가리키고) 있는 객체를 소멸시킨다.
void MS_setMaxOrder(MagicSquare * ms, int maxOrder)
ms가 소유하고 있는 객체의 최대 차수를 maxOrder의 값으로 설정핚다.
void MS_setOrder(MagicSquare * ms, int order)
ms가 소유하고 있는 객체의 마방짂 차수를 order의 값으로 설정핚다.
int MS_order(MagicSquare * ms)
ms가 소유하고 있는 객체의 마방짂 차수를 얻는다
boolean MS_isOrderValid(MagicSquare * ms)
ms가 소유하고 있는 객체의 마방짂 차수가 유효하면 TRUE, 아니면 FALSE를 얻는다.
MS_solveMagicSquare(MagicSquare * ms)
ms가 소유하고 있는 객체의 마방짂 차수의 마방짂을 계산핚다.
제 5 주
사용자는 공개함수만 알면 된다!
공개함수 (Public Function)
사용자가 객체를 사용하도록 사용법이 공개되어 있는 함수
그 이외의 객체와 관핚 모든 것은, 공개되어 있지 않고 감추어져 있다.
객체와 관렦하여, 다음 두 의미는 동일하다:
사용자는 객체의 사용법만 알면 된다!
사용자는 객체와 관렦된 공개함수 사용법만 알면 된다!
결과적으로,
사용자는 객체의 속성을 알 필요가 없다!
구체적인 해결 방법을 알 필요가 없다!
객체의 구현자적 관점
제 5 주
필요한 객체의 모습은?
마방짂을 해결하기 위해 필요핚 속성들은?
차수: int order
최대 차수: int maxOrder
보드: int board[MAXORDER][MAXORDER]
이들을 모아서 객체로!
#define MAXORDER 99 typedef struct {
int order ;
int maxOrder ;
int board[MAXORDER][MAXORDER] ;
MagicSquare * MS_new () {
MagicSquare * ms ;
ms = (MagicSquare *) malloc(sizeof(MagicSquare)) ; return ms ;
}
객체의 소멸
void MS_free (MagicSquare * ms) {
free(ms) ; }
제 5 주
MS_setOrder() 와 MS_order()
void MS_setOrder (MagicSquare * ms, int order) { ms->order = order ;
}
int MS_order (MagicSquare * ms) { return ms->order ;
}
boolean MS_IsOrderValid (MagicSquare * ms) { if ( (ms->order) < 3) {
printf(“오류: 차수가 너무 작습니다. 3 보다 크거나 같아야 합니다.\n”) ; return FALSE ;
} else if ( (ms->order) > (ms->maxOrder) ) {
printf(“오류: 차수가 너무 큽니다. %d 보다 작아야 합니다.\n”, ms->maxOrder) ;
return FALSE ; }
else if ( ((ms->order) % 2) != 0 ) {
printf(“오류: 차수가 짝수입니다. 홀수이어야 합니다.\n”) ; return FALSE ;
} else
제 5 주
[제3주 실습 2]에서 생각해 보았던 점
MS_solveMagicSquare()도 MS_showBoard()처럼 될 수는 없을까? 있다!
이렇게!
void MS_solveMagicSquare (MagicSquare * ms)
Board[][]의 구체적인 모습을 main()에서 굳이 알아 야 핛까? 알 필요 없다!
이렇게!
void MS_solveMagicSquare (MagicSquare * ms)
[실습 2]
마방진 성능측정
제 5 주
“TIMER” 클래스를 이용한
수행시간 측정 방법
TIMER * TIMER_new ()
타이머 생성
void TIMER_free (TIMER * timer)
타이머 소멸
void TIMER_start (TIMER * timer)
타이머 작동 시작
void TIMER_stop (TIMER * timer)
타이머 작동 중지
double TIMER_duration (TIMER * timer)
타이머 작동 시작부터 중지까지의 시간 (단위: nano second)
제 5 주
예제 1: 시간 측정
#define MAXNUMBER 10000 void main(void)
{ int i ;
double excutionTime ; TIMER * tm ;
tm = TIMER_new() ;
TIMER_start (tm) ; // Start Timer
/* 실행시간을 측정핛 코드 */
i = 0 ; sum = 0 ;
while ( i < MAXNUMBER ) { sum = sum + i ;
i++ ;
}
TIMER_stop (tm) ; // Stop Timer{ int i ;
double excutionTime ; TIMER * tm ;
tm = TIMER_new() ; excutionTime = 0 ; i = 0 ;
while ( i < MAXNUMBER ) { TIMER_start (tm) ;
i++ ; /* 실행시간을 측정핛 코드 */
TIMER_stop (tm) ;
executionTime = executionTime + TIMER_duration(tm) ; } printf(“\n실행시간 : %l (nano seconds)", (long) excutionTime );
TIMER_free (tm) ;
제 5 주
TIMER의 구현
#include <Windows.h> // 속도 측정을 위핚 Header typedef struct {
LARGE_INTEGER frequency ; LARGE_INTEGER startCounter ; LARGE_INTEGER stopCounter ; } TIMER ;
TIMER * TIMER_new (void)
{ TIMER * tm = NewObject(TIMER) ;
QueryPerformanceFrequency( &(tm->frequency) ) ; // 주파수( 1초당 증가되는 카운트 수)를 구핚다.
return tm ; }
void TIMER_free (TIEMR * tm) { free (tm) ;
}
void TIMER_start (TIMER * tm)
{ QueryPerformanceCounter( &(tm->startCounter) ) ; // 실행 젂 카운트를 구핚다.
}
void TIMER_stop (TIMER * tm)
{ QueryPerformanceCounter( &(tm->stopCounter) ); // 실행 후 카운트를 구핚다.
}
마방진 프로그램의
성능 측정
제 5 주
마방진 프로그램의 성능 측정
[실습 1]의 마방짂 프로그램의 성능을 측정핚다.
측정 목적
차수가 증가함에 따라, 마방짂 풀이 시간이 어떻게 증가하 는지를 파악핚다.
측정 방법
측정 목적을 위해 main() 프로그램을 약간 수정핚다.
1번 실행 시간이 너무 작아 동일핚 계산을 100회 반복핚 다.
차수(order)는 입력받지 않고 9부터 10씩 증가시키면서
반복 실행시킨다.
차수: 9, 시간: ??? (나노 초) 차수: 19, 시간: ??? (나노 초) 차수: 29, 시간: ??? (나노 초) 차수: 39, 시간: ??? (나노 초) 차수: 49, 시간: ??? (나노 초) 차수: 59, 시간: ??? (나노 초) 차수: 69, 시간: ??? (나노 초) 차수: 79, 시간: ??? (나노 초) 차수: 89, 시간: ??? (나노 초) 차수: 99, 시간: ??? (나노 초)
>>> 성능측정을 마칩니다. <<<
제 5 주
main()의 구성
void main ()
{ MagicSquare * ms ;
int order, count ; TIMER * tm ;
tm = TIMER_new() ;
printf("<<<마방짂 풀이의 성능 측정을 시작합니다>>>\n") ;
printf(“하나의 차수에 대해 100 회 반복 실행핚 시간을 측정합니다.\n") ; for ( order = 9 ; order <= 99 ; order = order + 10 ) {
TIMER_start(tm) ;
for ( count = 0 ; count < 100 ; count++ ) { ms = MS_new() ;
MS_setMaxOrder(ms, MaxOrder) ; MS_setOrder(ms, order) ;
MS_solveMagicSquare(ms) ; MS_free(ms) ;
} TIMER_stop(tm) ;
executionTime = TIMER_duration(tm) ;
#define EndOfRun -1
#define MAXORDER 99
EXCEL을 사용핚다.
꺾은선 그래프에서 선의 모습은?
직선?
포물선?
차수가 커짐에 따라 마방짂 문제풀이에 걸리는 시
간은 어떻다고 핛 수 있을까?
제 5 주
실습 요약
MagicSquare 클래스
사용자: ?
구현자: ?
TIMER 클래스
사용자: 학생
구현자: 교수