Day 3(강의):
보충문법
inline 함수 const의 사용 구조체의 선언
이름공간(namespace)
레퍼런스와 주소 전달 호출(reference & call-by-reference) 디폴트 파라미터
함수의 오버로딩(function overloading) new와 delete 연산자
bool형
보충 문법
inline 함수
C 스타일의 SQ 매크로 함수
프로그램의 빌드: 전처리(전처리기) -> 컴파일(컴파일러) -> 링크(링커) 7번째 줄: 오답 출력
=> #define SQ(x) ((x) * (x))로 수정 매크로 함수 대 일반 함수
성능 대 메모리 공간
5줄 내의 짧은 코드에 대해 매크로 함수 사용
01 02 03 04 0506 07 08 09 1011
#include <iostream>
using namespace std;
#define SQ(x) x * x int main(void) {
cout << SQ(8) << ‘\n';
cout << SQ(9+5) << '\n';
return 0;
}
01 02 03 04 0506 07 08 09
#include <iostream>
using namespace std;
int main(void)
{cout << 8 * 8 << '\n';
cout << 9+5 * 9+5 << '\n';
return 0;
} 전처리
C++ 스타일의 SQ 매크로 함수
4번째 줄: 컴파일러에게 매크로 처리 요청(컴파일러에 의해 문법 및 의미 검증) 01
0203 04 0506 0708 09 1011 1213 14
#include <iostream>
using namespace std;
inline int SQ(int x) {return x*x;
}
int main(void)
{cout << SQ(8) << ‘\n';
cout << SQ(9+5) << '\n';
return 0;
}
const의 사용
상수의 정의 const int val=10;
const double e=2.71828;
const와 포인터 데이터를 상수화
포인터를 상수화 01
0203
double e=2.71828;
const double * doublePtr=&e;
*doublePtr = 20.3027; // 컴파일 오류
01 0203 04 05
double e=2.71828;
double r=3.894;
double * const doublePtr=&e;
*doublePtr = 20.3027;
doublePrt = &r; // 컴파일 오류
구조체의 선언
C 스타일
C++ 스타일 0102
03 0405 0607 08
enum suit {clubs, diamonds, hearts, spades}; /* C 언어의 열거형 */
struct card { /* C 언어의 구조체 */
enum suit s;
int rank;
};
struct card deck[52];
0102 0304 0506 07 08
enum suit {clubs, diamonds, hearts, spades};
struct card {
suit s; // suit가 바로 형 이름 int rank;
};
card deck[52]; // card가 바로 형 이름
변수 선언 위치
원하는 위치 어디서나 변수를 선언하는 것이 가능
for문의 i 변수 -> 유효범위는 선언된 가장 안쪽 블록인 for문 내 0102
03 0405 0607
void int_deck(card d[]) {for (int i=0; i<52; i++) {
d[i].s = i/13;
d[i].rank = 1 + i % 13;
}}
이름공간(namespace)
번호공간과 이름공간
전화 번호충돌 문제: 번호공간 도입(지역번호, 국번호) -> 02-901-8345와 02-591-8345는 다른 번호
대형 프로그램의 이름충돌 문제: 이름공간 도입(범위 지정 연산자) -> A::z 함수와 C::z 함수는 다른 함수
02
901 591
783 8341
8341
8341 2580 3214
3214
2580
대형 프로그램의 전역 공간
A B
C int x
double x
char x void z(void)
void y(void)
void z(void)
void y(void)
번호공간 이름공간
범위 지정 연산자를 사용한 Hello 응용 프로그램
std::cout, std::cin, std::endl
using 키워드
0102 0304 05 0607
#include <iostream>
int main(void)
{std::cout << "hello world!" << std::endl;
return 0;
}
namespace std { cout …
cin … endl …
… }
0102 0304 0506 0708 09
#include <iostream>
using std::cout;
using std::endl;
int main(void)
{cout << "hello world!" << endl;
return 0;
}
이름공간 사용 예
이름공간이 다르면 같은 이름의 변수나 함수의 선언이 허용됨 using 키워드를 사용하면
0102 03 0405 0607 08 0910 1112 13 1415 1617 18 1920 2122
#include <iostream>
namespace A { void y(void) {
std::cout << "A 모듈의 y 함수" << std::endl;
} }
namespace B { void y(void) {
std::cout << "B 모듈의 y 함수" << std::endl;
}}
int main(void) {
A::y();
B::y();
return 0;
}
…
using A::y;
int main(void) {
y();
B::y();
return 0;
}
범위 지정 연산자로 전역변수에 접근
6번째 줄: 지역변수 val이 1 증가
6번째 줄: 전역변수 val이 1 증가
01 0203 0405 0607 08
int val=100; // 전역변수 int main(void)
{
int val=100; // 지역변수 val += 1;
return 0;
}
0102 0304 0506 07 08
int val=100; // 전역변수 int main(void)
{
int val=100; // 지역변수 ::val += 1;
return 0;
}
레퍼런스와 주소전달(reference & call-by-reference)
변수와 레퍼런스(별명)
메모리 방은 하나 이름은 둘
n으로 할 수 있는 작업 = nn으로 할 수 있는 작업 레퍼런스의 제약
10 int n=10;
int & nn=n;
0102 03 0405 0607 08 09
int main(void) {
int &nn1; // error!, 레퍼런스는 선언과 동시에 초기화 돼야 함 int &nn2=10; // error!, 상수로 초기화 될 수 없음
int n=10;
int & nn = n; // OK!
… }
레퍼런스 파라미터
값 전달 호출과 주소 전달 호출 레퍼런스를 사용한 주소 전달 호출
greater 함수의 a와 b 레퍼런스 파라미터 = main의 i와 j의 별명 -> a와 b에 대한 독립적인 메모리 방의 할당 없음
-> a와 b의 조작은 i와 j를 직접 조작
int greater(const int & a, const int & b): 레퍼런스를 사용한 상수 주소 전달 -> greater 함수 내의 a와 b를 변경하는 코드(컴파일 오류 발생)
01 02 03 0405 06 07 08 0910 11 12 13 1415 16 17 18 1920 21
#include <iostream>
using std::cout;
using std::endl;
int greater(int & a, int & b) { if(a > b) {
int temp = a;
a = b;
b = temp;
return 1;
} else
return 0;
}
int main(void) { int i=20, j=10, k;
k = greater(i, j);
cout << k << endl;
return 0;
}
int greater(int & a, int & b) {
if(a > b) { int temp = a;
a = b;
b = temp;
return 1;
} else
return 0;
} k = greater( i, j );
20 10
20
포인터를 사용한 주소 전달 호출
위험한 포인터 조작: 잘 못 사용하면 치명적인 error!
-> 동적 자료 구조에 한해 사용
01 0203 0405 06 0708 0910 11 1213 1415 16 1718 1920 21
#include <iostream>
using std::cout;
using std::endl;
int greater(int * a, int * b) { if(*a > *b) {
int temp = *a;
*a = *b;
*b = temp;
return 1;
}else return 0;
}
int main(void) { int i=20, j=10, k;
k = greater(&i, &j);
cout << k << endl;
return 0;
}
레퍼런스를 리턴하는 함수
7번째 줄의 a의 입장에서 보면 i가 별명 -> return a;는 return i; -> int & k = i;
지역변수는 레퍼런스로 리턴될 수 없음
01 0203 0405 06 0708 0910 11 1213 1415 16 1718
#include <iostream>
using std::cout;
using std::endl;
int & max(int & a, int & b) { if(a > b)
return a;
elsereturn b;
}
int main(void) {int i=20, j=10;
int & k = max(i, j);
cout << k << endl;
return 0;
}
int & max(int & a, int & b) {
if(a > b) return a;
else
return b;
} int & k = max( i, j );
20 10
디폴트 파라미터
5번째 줄처럼 디폴트 파라미터의 지정은 뒤부터 차례대로 0102
0304 05 0607 0809 10 1112 1314 15 1617
#include <iostream>
using std::cout;
using std::endl;
int boxVolume(int length, int width=1, int height=1) {return length*width*height;
}
int main(void)
{cout << boxVolume(5, 6, 3) << endl;
cout << boxVolume(5, 6) << endl; // boxVolume(5,6,1) cout << boxVolume(5) << endl; // boxVolume(5,1,1) return 0;
}
함수의 오버로딩(function overloading)
C 스타일(함수 이름을 달리 해야 함) double ave2(double n1, double n2)
double ave3(double n1, double n2, double n3)
함수의 이름은 같지만 파라미터의 형이나 개수가 달라야 함 리턴형만 다르면 error!
double ave(double n1, double n2) // 컴파일 error!
int ave(double n1, double n2)
01 0203 04 0506 0708 09 1011 1213 14 1516 1718 19 20
#include <iostream>
using std::cout;
using std::endl;
double ave(double n1, double n2) {
return ((n1 + n2) / 2.0);
}
double ave(double n1, double n2, double n3) {
return ((n1 + n2 + n3) / 3.0);
}
int main(void) {
cout << ave(3.0, 2.9, 2.0) << endl; // 10번째 줄의 ave 호출 cout << ave(3.5, 4.5) << endl; // 5번째 줄의 ave 호출 return 0;
}
new와 delete 연산자
C의 malloc과 free를 대신
int형 데이터 한 개의 저장을 위한 메모리 할당 int * i = new int;
*i = 5;
delete i;
길이가 25인 int형 배열을 위한 메모리 할당 int * intarray = new int[25];
delete [] intarray;
new는 malloc과 달리, 메모리 공간의 크기 계산과 포인터 형의 변환이 필요 없음 new는 공간 할당이 실패하면 NULL 포인터(0) 리턴
bool형
bool result = (x<z) && (z<y);
result 변수: true 또는 false 값을 가짐
2장. Pen 응용 프로그램
Day 4(강의):
응용 프레임워크의 개념
클래스와 객체의 개념
응용 프레임워크의 개념
pclaf(PC Little Application Framework) 응용 프로그래밍 환경
윈도우즈 API 응용 프로그램: C 언어로 작성, 60줄 이상의 Hello 응용(복잡) 응용 프레임워크(MFC, pclaf)
MFC 응용 프로그램: C++ 언어로 작성, MFC 구조 복잡, 10줄 이내의 Hello 응용 pclaf 응용 프로그램: C++ 언어로 작성, 간단한 교육용, 10줄 이내의 Hello 응용
-> 클래스, 객체, 상속 개념 전달에 적합 -> 그래픽 기능을 갖춘 기본 윈도우 제공 -> 간단한 사용법
Windows xp, Vista pclaf
Microsoft
Foundation Class Library(MFC) 윈도우즈 API
(Application Programming
Interface) 응용 프로그램
pclaf 응용 프로 그램
MFC 응용 프로그램
API 환경 객체지향
환경
클래스와 객체의 개념
Pen 프로젝트의 구성(pclaf + penApp.cpp 파일)
window
application
penApplication window line
virtual run virtual
mouseDown virtual paint
application
mouseDown paint run
virtual okBox
mouseDown paint pen-
Application clientX
clientY wout
- - -
timer- Interval
childWindow
wostream
menu
+ mainLAF
PC Little Application Framework (pclaf.h, pclaf.cpp)
penApp.cpp
line
run
childWindow
mouseDown paint timer
pen- Application
control
basicMenuItem basicButton editText staticText listBox
클래스와 객체
클래스 = 소프트웨어 부품원판(붕어빵 원판)
객체 = 클래스로부터 생성된 소프트웨어 부품(붕어빵)
window 클래스
theWindow, thisWindow, thatWindow 객체
window
window line
virtual run virtual
mouseDown virtual paint clientX clientY wout
- - -
line
window line
virtual run virtual
mouseDown virtual paint clientX clientY wout
- - -
line theWindow
window line
virtual run virtual
mouseDown virtual paint clientX clientY wout- - -
line thisWindow
window line
virtual run virtual
mouseDown virtual paint clientX clientY wout
- - -
line thatWindow
부품
부품(하드웨어 장치) = 정적인 속성(데이터 속성) + 동적인 속성(기능적인 속성) 비디오 플레이어는 홈 시어터 시스템을 구성하는 부품
비디오 플레이어 = 데이터 속성(일련번호, 제조사, 모델명, 가격, 무게, …) +
기능적인 속성(재생, 정지, 일시 정지, 앞으로 빨리 감기, …) 비디오 플레이어의 설계틀(클래스), 비디오 플레이어(객체)
비디오 플레이어, DVD 플레이어, CD 플레이어, 캠코더 -> 공통인 속성들을 뽑아 공통 설계
-> 공통 설계에 의해 기본 플레이어 제작
기본 플레이어
기본 플레이어
데이터 속성: 제조사, 모델명, 무게, …
기능적인 속성: 미디어 독립적인 켜기, 끄기, …(기능이 연계된 버튼 구비) 미디어 종속적인 재생, 앞으로 빨리 감기, …(버튼만 구비) 깔끔한 사용자 인터페이스 제공
-> 할 수 있는 기능들은 버튼으로 제공
-> 사용하는데 필요치 않은 사항은 박스처리
미디어 종속적인 버튼에 기능을 연계시켜 비디오 플레이어, DVD 플레이어, CD 플레이어, 캠코더 등으로 발전
=> 모든 플레이어의 제작에 재사용 되는 기본 부품
기본 플레이어
on 버튼(켜기 행위 요청)
기본 소프트웨어 부품
무엇을 어떻게 부품화?
비유:아래한글 - 비디오 플레이어 탐색기 - DVD 플레이어 익스플로러 - CD 플레이어 파워포인터 - 캠코더
무엇을?
아래한글, 탐색기, 익스플로러, 파워포인터의 공통 -> 윈도우 기반
윈도우는 응용 프로그램이 동작하는 기본 단위 -> 기본 소프트웨어 부품화 -> 기본 윈도우
어떻게?
기본 윈도우 = 데이터 속성(화면상의 위치, 가로와 세로의 크기, 바탕색,…) +
기능적인 속성(크기 조정, 이동, 아이콘화, 소멸,…) 데이터 속성 -> 변수(레코드) 정의(애트리뷰트, 멤버 변수)를 통해 기능적인 속성 -> 함수(메소드, 멤버 함수)를 통해
=> 패키지화
기본 윈도우
데이터 속성: 화면상의 위치, 가로와 세로의 크기, 바탕색,…
기능적인 속성: 응용 독립적인 크기조정, 이동, 소멸, …(기능을 연계, 함수로 구현)
응용 종속적인 클라이언트 영역 그리기, 편집, 탐색, 인터넷 서 핑, 컨텐츠 제작…(오픈, 함수 원형만 제공)
깔끔한 사용자 인터페이스 제공
-> 할 수 있는 기능들은 마우스 조작, 버튼, 메뉴 등으로 제공 -> 사용하는데 필요치 않은 사항은 은닉
응용 종속적인 기능을 연계시켜 아래한글, 탐색기, 익스플로러, 파워포인터 윈 도우 등으로 발전
=> 모든 응용 프로그램의 제작에 재사용 되는 기본 부품
close 버튼(소멸 행위를 요청)
마우스 드래깅(이동 행위를 요청)
마우스 드래깅(크기조정 행위를 요청) 시스템 메뉴
(소멸 행위를 요청)
기본 플레이어와 기본 윈도우의 유사성
window 클래스 = 45 멤버 변수 + 62 멤버 함수 virtual 키워드 -> 4장에서
window line
virtual run virtual
mouseDown virtual paint clientX clientY wout- - -
line
line(20,20,30,30)
paint() 기본 윈도우 객체(theWindow)
play
기본 플레이어
박스 처리
패키지 처리
on (버튼 클릭)
run() (메시지 전달)
window
window line
virtual run virtual
mouseDown virtual paint clientX clientY wout
- - -
line 공통 설계
멤버 함수의 오버로딩
void line(const int, const int, const int, const int);
void line(const point &, const point &);
화면상에 표시
메시지 전달
기본 플레이어의 on 버튼 누르기 = theWindow 객체에게 run 메시지 전달 theWindow.run();
응용 독립적인 멤버 함수: run, line, …(함수 원형 + 바디 제공) 응용 종속적인 멤버 함수: paint, mouseDown, …(함수 원형만 제공)
window line
virtual run
virtual mouseDown
virtual paint clientX 100
clientY 200 wout …
- - - …
line theWindow
run() (메시지 전달) 빈 윈도우 표시 코드
- - -
사용자 다음 입력 대기 코드 내부 접근
외부 접근은 메시지를 통해