Download presentation
Presentation is loading. Please wait.
1
C++ 프로그래밍 16 2009년 2학기 전자정보공학대학 컴퓨터공학부
2
헤더 파일과 구현 파일
3
#include 지시문(1) 하나의 소스 파일로 된 예제 소스 코드 #include <iostream>
#include <cmath> using namespace std; struct Point { int x, y; }; double Distance(Point p1, Point p2); int main() // 생략 double dist_a_b = Distance(a, b); } double Distance(Point p1, Point p2)
4
#include 지시문(2) #include 지시문을 사용해서 두 개의 소스 파일로 나누어 보자. // Example.h
struct Point { int x, y; }; double Distance(Point p1, Point p2); // Example.cpp #include <iostream> #include <cmath> using namespace std; #include “Example.h” int main() { // 생략 double dist_a_b = Distance(a, b); } double Distance(Point p1, Point p2)
5
#include 지시문(3) 두 가지 버전의 예제를 비교해보자. [18-3]
6
헤더파일과 구현파일을 나누는 방법 하나의 소스 코드로 이루어진 프로그램을 여러 개의 헤더 파일과 구현 파일로 나눌 때 다음의 규칙대로 하자. 규칙 1. 공유될 함수가 있는 구현 파일의 이름을 따서, 헤더 파일을 만든다. 규칙 2. 이 헤더 파일에 공유될 함수의 원형을 적어준다. 규칙 3. 공유될 함수를 호출할 구현 파일에서는 이 헤더 파일을 포함한다. 규칙 4. 구현 파일에서는 자기 자신에 대한 헤더 파일을 포함한다.
7
실전 테스트 (1) 다음의 세 구현 파일이 제대로 컴파일 될 수 있도록 고치고, 헤더 파일도 추가하자. // A.cpp
void A1() { A2(); } void A2() B1(); B2(); // B.cpp void B1() { } void B2() // Example.cpp int main() { A1(); B1(); return 0; }
8
실전 테스트 (2) 세 구현 파일의 호출 관계를 그림으로 그려보자. [18-7]
9
실전 테스트 (3) 앞에서 배운 규칙대로 한 결과 // A.h void A1(); void A2(); // B.h
void B1(); void B2(); // B.cpp #include “B.h” void B1() { } void B2() // A.cpp #include “A.h” #include “B.h” void A1() { A2(); } void A2() B1(); B2(); // Example.cpp #include “A.h” #include “B.h” int main() { A1(); B1(); return 0; }
10
다른 파일에 있는 구조체 사용하기 (1) 하나의 소스 파일로 된 예제 소스 코드 struct Point { int x, y;
}; double Distance(const Point& pt1, const Point& pt2) // 이 함수의 내용은 생략한다. return 0.0f; } int main() // 두 점을 만든다. Point a = {100, 100}; Point b = {200, 200}; // 함수를 호출한다. double dist; dist = Distance(a, b); return 0;
11
다른 파일에 있는 구조체 사용하기 (2) 여러 개의 파일로 나누어 보자. // Point.h struct Point {
int x, y; }; // Example2.h double Distance(const Point& pt1, const Point& pt2); // Example2.cpp #include “Point.h” #include “Example2.h” double Distance(const Point& pt1, const Point& pt2) { // 이 함수의 내용은 생략한다. return 0.0f; } // Example1.cpp #include “Point.h” #include “Exaple2.h” int main() { // 두 점을 만든다. Point a = {100, 100}; Point b = {200, 200}; // 함수를 호출한다. double dist; dist = Distance(a, b); return 0; }
12
다른 파일에 있는 구조체 사용하기 (3) 파일들의 포함 관계를 그림으로 그려보자. [18-10]
13
다른 파일에 있는 구조체 사용하기 (4) 다른 파일에 있는 구조체를 사용하기 위한 방법을 정리해보자.
규칙 1. 구조체의 이름을 따서 새로운 헤더 파일을 만든다. 규칙 2. 이 헤더 파일에 구조체의 정의 부분을 위치시킨다. 규칙 3. 구조체를 사용하는 구현 파일마다 이 헤더 파일을 포함시킨다.
14
헤더 파일이 두 번 포함되는 것 막기 전처리기를 사용해서 헤더 파일의 중복 포함을 막는 예 중복 포함을 막는 방법 정리
헤더 파일의 이름을 따서 심볼을 만든다 ( 예: POINT_H ) 헤더 파일의 제일 앞에 이 심볼을 사용해서 #ifndef, #define 명령을 추가한다. 헤더 파일의 제일 끝에 #endif를 추가한다. // Point.h #ifndef POINT_H #define POINT_H struct Point { int x, y; }; #endif
15
표준 라이브러리의 헤더 파일 표준 라이브러리의 헤더 파일은 <> 를 사용해서 포함한다.
우리가 만든 헤더 파일은 “”를 사용해서 포함한다. <> 를 사용한 경우에는 컴파일러와 함께 표준 라이브러리 설치된 디렉토리에서 헤더 파일을 찾는다. 반면에 “”를 사용한 경우에는 여러 분이 작업 중인 프로젝트가 위치한 디렉토리에서 헤더 파일을 찾는다. #include <iostream> #include <string> #include <cmath> #include “Example1.h”
16
객체 지향 프로그래밍의 이해 (Object Oriented Programming)
17
객체지향 프로그래밍의 비유(1) 객체지향 프로그래밍은 부품을 모아서 조립하는 과정이 비유할 수 있다. 여기서 객체를 부품이라고 볼 수 있다. [20-1]
18
객체지향 프로그래밍의 비유(2) 부품별로 분업할 수 있는 것처럼, 객체를 만들 때도 자신의 객체에 대해서만 노력을 집중할 수 있다. 제가 발생한 경우에 해당 부품만 교체하면 되듯이, 객체에 문제가 있는 경우에는 해당 객체만 고치면 된다. [20-2]
19
객체지향 프로그래밍의 비유(3) 하나의 부품을 여러 제품에 사용할 수 있는 것처럼, 잘 만들어 놓은 객체는 다음 번 프로젝트에도 재사용할 수 있다. 부품들의 규격이 정해져 있어야 조립이 가능한 것처럼, 객체간의 연결 부분도 잘 약속되어 있어야 한다. [20-4] [20-5]
20
클래스(Classes)와 객체(Objects) (1)
클래스와 객체는 ‘붕어빵 틀’과 ‘붕어빵’의 관계다. 혹은 ‘제품의 설계도’와 ‘제품’의 관계라고 말할 수도 있다. [20-6]
21
클래스(Classes)와 객체(Objects) (2)
문법적인 측면에서 바라본 클래스와 객체 [20-7]
22
캡슐화(Encapsulation) 캡슐화란 약속되지 않은 부분은 감싸서 숨겨버리는 것을 말한다. 캡슐화를 통해서 정보은닉을 달성할 수 있다. [20-10]
23
상속(Inheritance) 상속이란 기존 클래스를 토대로 새로운 클래스를 만드는 방법을 말한다. 예) 상속 모형
예) 붕어빵 틀을 상속받아서 수염 달린 붕어빵 틀을 만들기
24
다형성(Polymorphism) 다형성이란 서로 다른 객체를 동일한 방식으로 명령을 내릴 수 있는 성질을 말한다. 이 때 서로 다른 객체들은 같은 명령을 받지만 제각기 다른 방식으로 명령을 수행할 수 있다. 예) 백열들과 삼파장 램프는 동일한 소켓에 끼워서 사용할 수 있다. [20-13]
25
클래스와 객체
26
클래스의 정의 Point 클래스를 정의하는 예 // Point 클래스를 정의한다. class Point { public:
// 멤버 변수들 int x, y; // 멤버 함수 void Print() cout << "( " << x << ", " << y << ")\n"; } };
27
클래스의 정의 Point 클래스를 정의하는 예
28
객체의 생성과 사용(1) 클래스 객체를 생성하고 사용하는 예 // 객체를 생성한다. Point pt1, pt2;
pt1.x = 100; pt1.y = 100; pt2.x = 200; pt2.y = 200; // pt1, p2의 내용을 출력한다. pt1.Print(); pt2.Print();
29
객체의 생성과 사용(2) Print() 함수에서 사용하는 x, y의 의미 [21-3]
30
일반 함수와 멤버 함수의 차이점 다음과 같은 차이점을 가지고 있다.
외부에서 멤버 함수를 호출하기 위해서는 객체의 이름을 명시해주어야 한다. 멤버 함수 안에서는 객체의 이름을 명시하지 않고 멤버에 접근할 수 있다. 외부에서 접근 할 수 없도록 설정된 멤버라 할지라도 멤버 함수 안에서는 접근할 수 있다.
31
멤버 함수의 위치 클래스의 정의 바깥쪽에 멤버 함수를 정의한 예 class Point { public: // 멤버 변수
int x, y; // 멤버 함수 void Print(); }; void Point::Print() cout << "( " << x << ", " << y << ")\n"; }
32
멤버 함수 안에서의 이름 충돌 클래스의 정의 바깥쪽에 멤버 함수를 정의한 예 class Point { public:
// 멤버 변수 int x, y; // 멤버 함수 void Print(); }; void Point::Print() int x = 333; cout << "( " << x << ", " << y << ")\n"; }
33
객체를 사용한 초기화와 대입 일반 변수와 같은 방식으로 초기화와 대입 가능 Point pt1, pt2; pt1.x = 100;
pt1.y = 100; pt2.x = 200; pt2.y = 200; // pt1을 사용해서 새로운 pt3를 초기화 한다. Point pt3 = pt1; pt3.Print(); // pt2을 pt3에 대입한다. pt3 = pt2;
34
생성자와 소멸자 생성자는 객체를 생성할 때 자동으로 호출되는 함수이다. 소멸자는 객체를 소멸할 때 자동으로 호출되는 함수이다.
그러므로 생성자는 객체를 사용할 수 있도록 초기화 하는 코드를 넣기에 알맞은 장소이다. 소멸자는 객체를 소멸할 때 자동으로 호출되는 함수이다. 그러므로 소멸자는 객체가 사용한 리소스를 정리하는 코드를 넣기에 알맞은 장소이다.
35
디폴트 생성자(Default Constructors)
디폴트 생성자의 추가 class Point { public: int x, y; void Print(); Point(); }; Point::Point() x = 0; y = 0; } // 실제 실행 시.. Point pt; // 생성자가 호출된다. pt.Print();
36
인자가 있는 생성자(1) 인자가 있는 생성자의 추가 class Point { public: int x, y;
void Print(); Point(); Point(int initialX, int initialY); }; Point::Point(int initialX, int initialY) x = initialX; y = initialY; } // 중간 생략 Point pt(3, 5); pt.Print();
37
인자가 있는 생성자(2) 생성자로의 인자 전달
38
복사생성자(Copy Contructors)(1)
class Point { public: int x, y; void Print(); Point(); Point(int initialX, int initialY); Point(const Point& pt); }; Point::Point(const Point& pt) cout << "복사 생성자 호출됨!!\n"; x = pt.x; y = pt.y; } // 중간 생략 Point pt1(100, 100), pt2(200, 200); // pt1을 사용해서 새로운 pt3를 초기화 한다. Point pt3 = pt1; pt3.Print(); // pt2을 pt3에 대입한다. pt3 = pt2; 복사 생성자의 추가 [21-8]
39
복사생성자(Copy Contructors)(2)
복사 생성자는 자기 자신의 타입에 대한 레퍼런스를 인자로 받는 생성자다. 그러므로 다음의 두 가지 원형 중 한 가지 모습을 가질 수 있다. 다음과 같은 두 가지 방식으로 복사 생성자를 호출할 수 있다. Point( Point& pt ); Point( const Point& pt ); Point pt1; Point pt2 = pt1; Point pt3( pt1 );
40
얕은 복사와 깊은 복사 기본적으로 제공되는 복사 생성자는 얕은 복사를 하도록 구현되어 있다. 깊은 복사가 필요하다면 별도의 복사 생성자를 만들어야 한다. [21-11]
41
반드시 생성자가 필요한 경우 멤버 변수중에 레퍼런스 변수 혹은 Const 속성의 변수가 있는 경우에는 반드시 생성자에서 초기화 해주어야 한다. class NeedConstructor { public: const int maxCount; int& ref; int sample; NeedConstructor(); }; NeedConstructor::NeedConstructor() : maxCount(100), ref(sample) sample = 200; }
42
소멸자(1) 소멸자를 사용해서 할당한 메모리를 해제하는 예 class DynamicArray { public:
int* arr; DynamicArray(int arraySize); ~DynamicArray(); }; DynamicArray::DynamicArray(int arraySize) // 동적으로 메모리를 할당한다. arr = new int [arraySize]; } DynamicArray::~DynamicArray() // 메모리를 해제한다. delete[] arr; arr = NULL;
43
소멸자(2) 소멸자를 사용해서 할당한 메모리를 해제하는 예 int main() { // 몇 개의 정수를 입력할지 물어본다.
소멸자를 사용해서 할당한 메모리를 해제하는 예 int main() { // 몇 개의 정수를 입력할지 물어본다. int size; cout << "몇 개의 정수를 입력하시겠소? "; cin >> size; // 필요한 만큼의 메모리를 준비한다. DynamicArray da(size); // 정수를 입력 받는다. for (int i = 0; i < size; ++i) cin >> da.arr[i]; // 역순으로 정수를 출력한다. for (i = size - 1; i >= 0; --i) cout << da.arr[i] << " "; cout << "\n"; // 따로 메모리를 해제해 줄 필요가 없다. return 0; }
44
소멸자(3) DynamicArray 객체를 생성한 모습 [21-20]
Similar presentations