Download presentation
Presentation is loading. Please wait.
1
Game Programming 03 - Tools of trade
2010년 2학기 디지털콘텐츠전공
2
Tools of trade for a programmer
Microsoft Visual Studio C/C++ brief review and practices
3
시작하기 전에: Coding의 과정 에디터 목적 파일1 컴파일러 목적 파일n 링커 프로그램 디버깅 Source file1
Source file n 목적 파일1 컴파일러 목적 파일n 링커 프로그램 디버깅
4
Source files and headers
A file with the extension such as .c, .cc, cpp, cxx. A translation unit The compiler translates one source file at a time Header file: Special source file for sharing information between translation unit Type declarations, function prototypes Preprocessor of VC replaces “#include” statements in source files with the header files
5
Libraries, executables, DLLs
Object file (.obj (windows) or .o (linux)): A machine code after compiling a translation unit Relocatable : memory addresses is not fixed Unlinked : some functions and global data can be outside of the source file ( not resolved yet) Library (.lib) A simple archive of .objs such as .zip file Executable (.exe) Obj files and libraries are linked by a linker A fully resolved machine code Final relative address in memory All functions, and global data are resolved
6
Libraries, executables, DLLs
Dynamic Linked Library (DLL) It is a library It contains functions Can be called by an other executables It is an executable It can be called independently Having its own start-up and shut-down code Can be called by an executable that is Partially unlinked : having functions that are not resolved yet Dlls can be updated without changing any executables that use them.
7
IDE 통합 개발 환경: Integrated Development Environment
컴퓨터 소프트웨어를 개발할 수 있게 해주는 소프트웨어 Text Editor + Compiler + Linker + Debugger +…
8
Projects and Solutions
Projects (.vcproj): A collection of source files to generate libraries, executables, dlls. As a form of XML containing various setings Visual Studio .NET (version 7) Visual Studio (version 8) Visual Studio (version 9) Solutions (.sln) A collection of projects
9
Build configurations In each stage, there are many options.
C/C++ preprocessor Compiler Linker C:\> cl /c foo.cpp /Fo foo.obj /Wall /Od /Zi
10
Build configurations Preprocessor: Handling #include and #define macro
#define is good because you can communicate with various build options without changing your source code Some predefined macro _DEBUG, _MSC_VER, _WIN32 …. void f() { #ifdef _DEBUG printf(“calling function f() \n”); #endif }
11
Build configurations Compiler setting: Debugging information
used by a debugger to step through your code Makes executables larger and traceable Inline function setting Optimization setting
12
Build configurations Linker setting:
What type of output to produce: .exe or .dll Which external libraries should be linked Which directory paths to search to find libs Stack size, preferred base address and so on.
13
Build configurations Typical build configurations Debug Release
A very slow version of your program All optimization turned off All function inlining disabled Full debugging information included Release A faster version of your program Some debugging information and assertions turned on To test a speed representative of the final product while still can provide a limited ability to debug Production The fastest and leanest build Final version without any debugging information All assertions are usually turned off Optimizations are turned on
14
Project configuration tutorials
Configuration properties/General Configuration properties/Debugging Configuration properties/C++ Configuration properties/Linker
15
Linking in depth Declaration vs. Definition Declaration: Definition:
A description of a data object or function Name of the type or a function prototype Definition: Function or memory itself Definition is always a declaration. Reverse is not always the case
16
헤더 파일과 구현 파일
17
#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)
18
#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)
19
#include 지시문(3) 두 가지 버전의 예제를 비교해보자. [18-3]
20
헤더파일과 구현파일을 나누는 방법 하나의 소스 코드로 이루어진 프로그램을 여러 개의 헤더 파일과 구현 파일로 나눌 때 다음의 규칙대로 하자. 규칙 1. 공유될 함수가 있는 구현 파일의 이름을 따서, 헤더 파일을 만든다. 규칙 2. 이 헤더 파일에 공유될 함수의 원형을 적어준다. 규칙 3. 공유될 함수를 호출할 구현 파일에서는 이 헤더 파일을 포함한다. 규칙 4. 구현 파일에서는 자기 자신에 대한 헤더 파일을 포함한다.
21
실전 테스트 (1) 다음의 세 구현 파일이 제대로 컴파일 될 수 있도록 고치고, 헤더 파일도 추가하자. // A.cpp
void A1() { A2(); } void A2() B1(); B2(); // B.cpp void B1() { } void B2() // Example.cpp int main() { A1(); B1(); return 0; }
22
실전 테스트 (2) 세 구현 파일의 호출 관계를 그림으로 그려보자. [18-7]
23
실전 테스트 (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; }
24
다른 파일에 있는 구조체 사용하기 (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;
25
다른 파일에 있는 구조체 사용하기 (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; }
26
다른 파일에 있는 구조체 사용하기 (3) 파일들의 포함 관계를 그림으로 그려보자. [18-10]
27
다른 파일에 있는 구조체 사용하기 (4) 다른 파일에 있는 구조체를 사용하기 위한 방법을 정리해보자.
규칙 1. 구조체의 이름을 따서 새로운 헤더 파일을 만든다. 규칙 2. 이 헤더 파일에 구조체의 정의 부분을 위치시킨다. 규칙 3. 구조체를 사용하는 구현 파일마다 이 헤더 파일을 포함시킨다.
28
헤더 파일이 두 번 포함되는 것 막기 전처리기를 사용해서 헤더 파일의 중복 포함을 막는 예 중복 포함을 막는 방법 정리
헤더 파일의 이름을 따서 심볼을 만든다 ( 예: POINT_H ) 헤더 파일의 제일 앞에 이 심볼을 사용해서 #ifndef, #define 명령을 추가한다. 헤더 파일의 제일 끝에 #endif를 추가한다. // Point.h #ifndef POINT_H #define POINT_H struct Point { int x, y; }; #endif
29
표준 라이브러리의 헤더 파일 표준 라이브러리의 헤더 파일은 <> 를 사용해서 포함한다.
우리가 만든 헤더 파일은 “”를 사용해서 포함한다. <> 를 사용한 경우에는 컴파일러와 함께 표준 라이브러리 설치된 디렉토리에서 헤더 파일을 찾는다. 반면에 “”를 사용한 경우에는 여러 분이 작업 중인 프로젝트가 위치한 디렉토리에서 헤더 파일을 찾는다. #include <iostream> #include <string> #include <cmath> #include “Example1.h”
30
Usual error: multiply-defined
// Example1.cpp int g_external; void functionA(); int main() { g_external = 20; functionA(); cout<<g_external; return 0; } // Example2.cpp int g_external; void functionA() { g_external = 10; }
31
Usual error: multiply-defined
extern // Example1.cpp int g_external; void functionA(); int main() { g_external = 20; functionA(); cout<<g_external; return 0; } // Example1.cpp int g_external; extern void functionA(); int main() { g_external = 20; functionA(); cout<<g_external; return 0; } // Example2.cpp extern int g_external; void functionA() { g_external = 10; }
32
Usual error: multiply-defined
static: only valid in one translation unit // Example1.cpp int g_external; extern void functionA(); int main() { g_external = 20; functionA(); cout<<g_external; return 0; } // Example2.cpp static int g_external; void functionA() { g_external = 10; }
33
Debuging? 프로그램 시 드는 의문: 해결법: 프로그램이 제대로 동작하고 있는 걸까? OR
지금 현재 변수 값이 얼마일까? 해결법: DEBUG 모드를 활용하자! Debug 모드가 주는 장점들 문장 출력 (printf와 비슷) : TRACE 이용 프로그램 일시 중단 : 중단점 활용 변수 값 조사 : 조사식/호출스택 이용 값의 유효성 상시 검사: ASSERT 이용
34
Different modes for compiling
Debug Mode : 프로그램 개발 모드 여러가지 편리한 기능 제공 수행 속도가 떨어짐 (대규모 메모리 생성 시) Release Mode : 프로그램 배포 모드 프로그램 용량 최적화 수행 속도 최적화 활성 구성 설정 바꾸기: 빌드 구성관리자
35
Debug Mode 활용하기 먼저 활성구성을 Debug Mode로 바꿈 F5를 누르거나 “디버깅시작” 실행
디버깅 기능들이 모두 사용 가능 하게 됨 TRACE, 중단점, 조사식 등의 기능 사용 Ctrl + F5를 누르거나 “디버깅하지 않고 시작” 실행 디버깅 기능이 사용 안됨 빠르게 테스트 할 때 활용
36
TRACE 원하는 문장을 출력창에 표시한다. 사용법 (printf와 동일) 출력결과:
TRACE( “Now Running! /n”); // 문장 출력 TRACE( “i= %d /n”, i); // 변수값 출력
37
중단점 (break point) 프로그램의 실행을 일시 멈추고 싶은 곳에 설정 중단점 지정 행의 바로 앞에서 멈춘다.
중단점 설정: F9 키 중단점 해제: F9 키 중단점 지정 행의 바로 앞에서 멈춘다. 한 줄씩 실행: F10 키 함수 일 경우는 하나씩 함수가 실행됨 함수 속으로 들어가 실행: F11 키 함수 코드 내로 들어감 Conditional Break point Condition: break의 조건 지정 Hit count: 회수에 따라 동장
38
호출 스택 (실행 중단 시) 현재 중단 된 시점의 함수 호출 스택을 표시 함수의 실행 경로 확인 가능
함수 간을 이동하면 변수값을 조사하는데 활용 <창 표시법: 디버그 창 호출 스택 >
39
변수 값 조사 (실행 중단 시) 변수들의 현재 값을 표시함 (watch window) 자동: 전역 또는 지역 변수 값 표시
지역: 현재 함수 내에서 사용되는 지역 변수 값 표시 조사식: 사용자가 원하는 변수 또는 수식 값 표시 배열이나, pointer값도 조회 가능 <창 표시법: 디버그 창 조사식/자동/지역 >
40
변수 값 조사 (실행 중단 시) 유용한 팁 (Watch window):
,d : displaying a value in decimal notation ,x : displaying a value in hexadecimal notation ,n (any positive integer): treating as a array with the size of n
41
ASSERT 활용 값의 유효성을 확인하기 위해 활용 사용법: 조사식의 값이 false 이면 프로그램 실행 중단 시킴 사용 예:
ASSERT ( i==0 ); // i가 0인지 확인 ASSERT ( i<0 ); // i가 0보다 작은지 확인 ASSERT ( func1() ); // func1을 수행하고 // 반환값이 true인지 확인
42
C++ Review and best practices
C + Class C의 효율성 + 객체지향개념(object-oriented)
43
절차지향과 객체지향 객체지향의 배경 객체지향과 절차지향의 비교 소프트웨어 모듈의 재사용과 독립성을 강조
절차지향 (Procedural-Oriented) : 데이터 구조와 그 데이터를 변화시키는 procedure/function으로 구성 객체지향 (Object-Oriented) : 객체들이 메시지(message)를 통하여 통신함으로써 원하는 결과를 얻는다. 각 객체는 고유의 속성(attribute)와 데이터를 처리할 수 있는 메소드(method)로 구성
44
절차지향과 객체지향 비구조적 구조적/절차지향 객체지향
45
객체 객체(Object) 효율적으로 정보를 관리하기 위하여, 사람들이 의미를 부여하고 분류하는 논리적인(개념적인) 단위 실 세계에 존재하는 하나의 단위에 대한 소프트웨어적 표현 관련된 변수와 함수의 묶음 객체의 구성 속성의 값을 나타내는 데이터(data) - attribute 데이터를 변경하거나 조작하는 기능(function) – method
46
객체지향 프로그래밍의 특징 캡슐화 (encapsulation) 상속 (inheritance) 다형성 (polymorphism)
47
데이터와 그 기능을 묶는 단위:클래스
48
클래스의 정의 Point 클래스를 정의하는 예 // Point 클래스를 정의한다. class Point { public:
// 멤버 변수들 int x, y; // 멤버 함수 void Print() cout << "( " << x << ", " << y << ")\n"; } };
49
클래스의 정의 Point 클래스를 정의하는 예
50
객체의 생성과 사용(1) 클래스 객체를 생성하고 사용하는 예 // 객체를 생성한다. Point pt1, pt2;
pt1.x = 100; pt1.y = 100; pt2.x = 200; pt2.y = 200; // pt1, p2의 내용을 출력한다. pt1.Print(); pt2.Print();
51
객체의 생성과 사용(2) Print() 함수에서 사용하는 x, y의 의미 [21-3]
52
멤버 함수의 위치 클래스의 정의 바깥쪽에 멤버 함수를 정의한 예 class Point { public: // 멤버 변수
int x, y; // 멤버 함수 void Print(); }; void Point::Print() cout << "( " << x << ", " << y << ")\n"; }
53
생성자와 소멸자 생성자는 객체를 생성할 때 자동으로 호출되는 함수이다. 소멸자는 객체를 소멸할 때 자동으로 호출되는 함수이다.
그러므로 생성자는 객체를 사용할 수 있도록 초기화 하는 코드를 넣기에 알맞은 장소이다. 소멸자는 객체를 소멸할 때 자동으로 호출되는 함수이다. 그러므로 소멸자는 객체가 사용한 리소스를 정리하는 코드를 넣기에 알맞은 장소이다.
54
디폴트 생성자(Default Constructors)
디폴트 생성자의 추가 class Point { public: int x, y; void Print(); Point(); }; Point::Point() x = 0; y = 0; } // 실제 실행 시.. Point pt; // 생성자가 호출된다. pt.Print();
55
인자가 있는 생성자 인자가 있는 생성자의 추가 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();
56
소멸자 소멸자를 사용해서 할당한 메모리를 해제하는 예 class DynamicArray { public: int* arr;
DynamicArray(int arraySize); ~DynamicArray(); }; DynamicArray::DynamicArray(int arraySize) // 동적으로 메모리를 할당한다. arr = new int [arraySize]; } DynamicArray::~DynamicArray() // 메모리를 해제한다. delete[] arr; arr = NULL;
57
객체의 동적인 생성 동적 메모리 할당을 사용해서 객체를 생성하는 예 Point pt(50, 50);
Point* p1 = new Point(); // 디폴트 생성자 사용 Point* p2 = new Point(100, 100); // 인자있는 생성자 사용 Point* p3 = new Point( pt); // 복사 생성자 사용 p1->Print(); p2->Print(); p3->Print(); delete p1; delete p2; delete p3;
58
접근 권한 설정하기(1) 멤버의 접근 권한을 설정하는 예 class AccessControl { public:
char publicData; void publicFunc() {}; protected: int protectedData; void protectedFunc() {}; private: float privateData; void privateFunc() {}; }; int main() // 객체를 생성하고, 각 멤버에 접근해보자 AccessControl ac; ac.publicData = 'A'; // 성공 ac.publicFunc(); // 성공 ac.protectedData = 100; // 실패 ac.protectedFunc(); // 실패 ac.privateData = 4.5f; // 실패 ac.privateFunc(); // 실패 return 0; } 멤버의 접근 권한을 설정하는 예
59
접근 권한 설정하기(2) 멤버의 접근 권한 설정하기 접근 권한 키워드에 대한 요약 (뒤에서 더욱 자세히 분류) [21-23]
public : 외부에서의 접근을 허용한다. protected, private : 외부에서 접근할 수 없다. [21-23]
60
객체지향 프로그래밍의 특징 캡슐화 (encapsulation) 상속 (inheritance) 다형성 (polymorphism)
61
캡슐화(encapsulation) 데이터와 함수를 묶음 데이터 은폐(information hiding)를 지원
62
캡슐화(encapsulation) 캡슐화는 데이터와 그것을 조작하는 코드를 같이 묶는 구조
객체 안에서 코드와 데이터는 비공개(private)될 수도 있고, 공개(public)될 수도 있다. 외부의 간섭과 오용을 막을 수 있음.
63
캡슐화(encapsulation) 캡슐화는 데이터와 그것을 조작하는 코드를 같이 묶는 구조
객체 안에서 코드와 데이터는 비공개(private)될 수도 있고, 공개(public)될 수도 있다. 외부의 간섭과 오용을 막을 수 있음.
64
상속(inheritance) 기존 데이터타입의 특성을 간직하면서도 특화된 타입을 만들어 내는 기법
65
상속(inheritance) 다른 객체의 특성을 이어 받아 새로운 개체를 생성
일반적인 성질 자신만의 특징들을 추가 계층적인 클래스화(hierarchical classification) Parent Class Child Class 객체가 속한 클래스와 객체 고유의 성질을 함께 정의 가능. 코드의 재사용성 증가!
66
다형성(polymorphism) 여러 타입을 다룰 수 있는 특성
67
다형성(polymorphism) 하나의 이름으로 여러 동작들을 지정 Examples: 하나의 함수명, 다양한 목적
자료형에 의해서 동작 결정. Examples: C : abs()-정수, labs()-배정도 정수, fabs()-실수 C++: abs()-정수, 배정도 정수, 실수 하나의 함수명, 다양한 목적 함수 중복(function overloading). 다형성의 이점 비슷한 동작 부류들을 같은 인터페이스로 지정되는 것을 허용, 복잡성을 줄여 줌.
68
상속과 포함
69
상속 앞으로의 예제 설명: 문서저장클래스 HTML저장클래스 string filename string contents
string font int fontsize string fontcolor string filename string contents
70
상속 앞으로의 예제 설명: HTML저장클래스 문서저장클래스 문서저장클래스 string filename
string contents string filename string contents string font int fontsize string fontcolor
71
생성자와 소멸자 자식 객체가 생성될 때, 자식 클래스의 생성자 뿐만 아니라 부모 클래스의 생성자도 호출된다.
부모 클래스에 오버로드된 여러 생성자가 있다면 그 중에서 어떤 생성자가 호출될 지 결정할 수 있다. (다음 페이지 참조) [22-13]
72
부모 클래스의 생성자(1) 자식 클래스의 생성자에서 부모 클래스의 생성자를 지정하는 예 // HTMLWriter.h
class HTMLWriter : public DocWriter { public: HTMLWriter(void); HTMLWriter(const string& fileName, const string& content); ~HTMLWriter(void); ...
73
부모 클래스의 생성자(2) 자식 클래스의 생성자에서 부모 클래스의 생성자를 지정하는 예 // HTMLWriter.cpp
HTMLWriter::HTMLWriter(const string& fileName, const string& content) : DocWriter( fileName, content) // 부모의 생성자 지정 { // 디폴트 폰트를 지정한다. _fontName = "굴림"; _fontSize = 3; _fontColor = "black"; } ...
74
부모와 자식 객체 간의 대입(1) 부모 클래스의 객체를 자식 클래스의 객체에 대입할 수 없다.
HTMLWriter hw; // 자식 클래스의 객체 생성 DocWriter dw; // 부모 클래스의 객체 생성 // 부모 클래스의 객체를 자식 클래스의 객체로 대입 hw = dw; // Error!! [22-17]
75
부모와 자식 객체 간의 대입(2) 자식 클래스의 객체를 부모 클래스의 객체에 대입할 수 있다.
HTMLWriter hw; // 자식 클래스의 객체 생성 DocWriter dw; // 부모 클래스의 객체 생성 // 자식 클래스의 객체를 부모 클래스의 객체로 대입 dw = hw; // OK [22-19]
76
포인터, 레퍼런스의 형변환(1) 자식 클래스의 포인터로 부모 객체를 가리킬 수 없다.
DocWriter dw; // 부모 클래스의 객체 생성 // 자식 클래스의 포인터 변수로 부모 객체를 가리킨다. HTMLWriter* phw = &dw; // Error!! [22-20]
77
포인터, 레퍼런스의 형변환(2) 부모 클래스의 포인터로 자식 객체를 가리킬 수 있다.
HTMLWriter hw; // 자식 클래스의 객체 생성 // 부모 클래스의 포인터 변수로 자식 객체를 가리킨다. DocWriter* pDW = &hw; // OK [22-22]
78
포인터, 레퍼런스의 형변환(3) 레퍼런스의 경우도 포인터와 동일한 규칙을 갖는다.
자식 클래스의 레퍼런스로 부모 객체를 참조할 수 없다. 부모 클래스의 레퍼런스로 자식 객체를 참조할 수 있다. DocWriter dw; // 부모 클래스의 객체 생성 // 자식 클래스의 레퍼런스 변수로 부모 객체를 참조한다. HTMLWriter& hw = dw; // Error!! HTMLWriter hw; // 자식 클래스의 객체 생성 // 부모 클래스의 레퍼런스 변수로 자식 객체를 참조한다. DocWriter& dw = hw; // OK
79
접근 제어(1) 접근 제어 키워드 접근 제어 가이드라인 외부로부터 숨겨야 하는 멤버는 protected로 지정한다.
그 밖의 경우는 public으로 지정한다. 반드시 자식 클래스에 숨기고 싶다면 private로 지정한다.
80
접근 제어(2) 상속과 관련해서 접근 제어 키워드를 실험해 보자. class Parent { private: int priv;
protected: int prot; public: int pub; }; class Child : public Parent void AccessParents() int n; // 부모의 멤버에 접근을 시도 n = priv; // 실패 n = prot; // 성공 n = pub; // 성공 }
81
포함과 상속의 구분 Has-a 관계와 Is-a 관계 포함과 상속을 구분해서 사용하기 위한 가이드라인
Has-a 관계 : A 가 B 를 가지고(포함하고) 있는 관계 예) 자동차는 타이어를 가지고 있다. Is-a 관계 : A 가 B 인 관계 예) 사과는 과일이다. 포함과 상속을 구분해서 사용하기 위한 가이드라인 Has-a 관계의 경우에는 포함을 사용한다. Is-a 관계의 경우에는 상속을 사용한다.
82
상속의 연습 – 도형 class 만들기 Shape Class 정의하기 Rectangle Class 정의하기
맴버변수: float _x,_y 생성자: Shape(float x, float y) _x와 _y의 값을 설정 맴버함수: void Draw() const 아래와 같은 내용 출력 [SHAPE] position = ( ‘_x값’, ‘_y값’ ) Rectangle Class 정의하기 Shape Class로부터 상속 맴버변수: float _width, _height 생성자: Rectangle(float x, float y, float w, float h) 아래와 같은 내용 출력 [RECTANGLE] position = ( ‘_x값’, ‘_y값’), size = (‘_width’, ‘_height’)
83
상속의 연습 – 도형 class 만들기 Circle Class 정의하기 Shape Class로부터 상속
맴버변수: float _radius 생성자: Circle(float x, float y, float radius) 맴버함수: void Draw() const 아래와 같은 내용 출력 [CIRCLE] position = ( ‘_x값’, ‘_y값’), radius = ‘_radius’
84
상속의 연습 – 도형 class 만들기 도형 Class 테스트 int main() { Shape a(100,40);
Rectangle b(120,40,50,20); Circle c(200,100,50); a.Draw(); b.Draw(); c.Draw(); return 0; }
85
Rectangle Class : Shape Class Circle Class : Shape Class
Shape(float x, float y) void Draw() const float _x float _y Rectangle Class : Shape Class Rectangle(float x, float y, float w, float h) void Draw() const float _width float _height Circle Class : Shape Class Circle(float x, float y, float r) void Draw() const float _radius
86
가상함수와 오버라이딩 (virtual function and overriding)
87
그림 그리는 프로그램 여러 가지 형태의 도형을 저장하고 싶다 각각의 ARRAY?? 포인터의 형변환
88
포인터의 형변환 부모 클래스의 포인터로 자식 객체를 가리킬 수 있다. HTMLWriter hw; // 자식 클래스의 객체 생성
// 부모 클래스의 포인터 변수로 자식 객체를 가리킨다. DocWriter* pDW = &hw; // OK [22-22]
89
포인터의 형변환 이용 1. 부모(base) 클래스 포인터의 배열을 설정 2. 필요 시 마다 new를 이용 자식class 생성
4. 다 사용 했으면 delete를 이용 메모리 해제
90
다양한 클래스의 객체를 배열에 담기(1) 도형 클래스의 객체들을 배열에 담아서 사용하는 예
Shape* shapes[5] = {NULL}; shapes[0] = new Circle( 100, 100, 50); shapes[1] = new Rectangle( 300, 300, 100, 100); shapes[2] = new Rectangle( 200, 100, 50, 150); shapes[3] = new Circle(100, 300, 150); shapes[4] = new Rectangle( 200, 200, 200, 200); for (int i = 0; i < 5; ++i) shapes[i]->Draw(); for (i = 0; i < 5; ++i) { delete shapes[i]; shapes[i] = NULL; }
91
다양한 클래스의 객체를 배열에 담기(2) 배열과 객체들의 메모리 구조 [23-5]
92
Draw의 실행 결과가 이상하다?? 부모(base) 클래스의 함수가 호출됐다?!
93
가상함수 가상 함수 부모 클래스의 포인터로 자식 클래스를 가르킬 경우: 객체의 실제 내용에 따라 불릴 순 없을까?
같은 이름의 함수의 실행은 포인터 타입이 우선 객체의 실제 내용에 따라 불릴 순 없을까? 컴파일 시에 결정되지 않고 함수가 런타임 시 결정 맴버 함수의 동적인 선택(동적바인딩)! 다형성 가상함수
94
가상함수의 선언 부모 클래스에서 함수 선언부분에 virtual 이라고 추가 구현부분은 그대로 나둔다. class parent
구현부분은 그대로 나둔다. class parent { public: virtual void DoIt(); }; class child : class parent void DoIt();
95
Draw 문제의 해결 shape 클래스의 Draw() 선언부분 수정 virtual void Draw() const
96
다형성(Polymorphism)과 가상함수(1)
다른 분야에서의 다형성의 의미 객체지향 프로그래밍에서의 다형성: 타입에 관계 없이 동일한 방법으로 다룰 수 있는 능력 예) Circle이나 Rectangle 객체들을 타입에 상관 없이 Shape 객체처럼 다룬다. [표 23-1]
97
다형성(Polymorphism)과 가상함수(2)
다형성은 객체간의 결합(Coupling)을 약하게 만들어서, 객체 간의 연결을 유연하게 해준다. // 도형을 원점으로 이동하는 함수 void Controller::MoveToOrigin( Shape* p ) { p->Move( 0, 0 ); p->Draw(); } [23-7]
98
오버로딩과 오버라이딩 오버로딩(Overloading) 오버라이딩(Overriding)
호출 인자가 다를 경우에 알맞은 것을 선택 ex) void DoIt( ); void DoIt(int i); 오버라이딩(Overriding) 부모 객체의 함수를 자식 객체에서 재정의 ex) parent::DoIt( ); child::DoIt( );
99
오버로딩과 오버라이딩 부모 클래스에서 오버로드 된 함수 중에서 어느 것 하나라도 오버라이드 하면 나머지 다른 함수들도 모두 사용할 수 없다. class Pet { public: void Eat(); void Eat(const string& it); string name; }; class Dog : public Pet void Eat(); // 하나만 재정의 [23-11]
100
오버로딩과 오버라이딩 부모 클래스에서 오버로드 된 함수 중에서 어느 것 하나라도 오버라이드 하면 나머지 다른 함수들도 모두 사용할 수 없다. int main() { // 강아지 생성 Dog dog1; dog1.name = "Patrasche"; // 두 가지 Eat() 함수를 호출한다. dog1.Eat(); dog1.Eat( "milk" ); // Error!! return 0; } [23-11]
101
참고서적: Effective C++
102
집에서 해 볼 일: http://www.ogre3d.org/tikiwiki/Tutorials
OGRE3D Basic tutorial 1~3 까지 따라해 보기
Similar presentations