340 likes | 549 Views
C++ 프로그래밍 12. 2008 년 2 학기 전자정보공학대학 컴퓨터공학부. Outline. 함수. Announcement. 중간고사 : 필기고사 10 월 14 일 ( 화요일 ) 수업시간 Closed Book 문제유형 : 작년 시험 문제 참고 ( 홈페이지에 게시 ) 실습고사 10 월 21 일 ( 화요일 ) 수업시간 Closed Book. 포인터와 레퍼런스의 사용. 반환되어야 하는 값이 2 개 이상일 때 ? 포인터를 사용 레퍼런스를 사용. 포인터 변수를 인자로 전달하기 (1).
E N D
C++ 프로그래밍 12 2008년 2학기 전자정보공학대학 컴퓨터공학부
Outline • 함수
Announcement • 중간고사: • 필기고사 • 10월 14일 (화요일) 수업시간 • Closed Book • 문제유형: 작년 시험 문제 참고 (홈페이지에 게시) • 실습고사 • 10월 21일(화요일) 수업시간 • Closed Book
포인터와 레퍼런스의 사용 • 반환되어야 하는 값이 2개 이상일 때? • 포인터를 사용 • 레퍼런스를 사용
포인터 변수를 인자로 전달하기(1) • 나누기를 하여 몫과 나머지를 구한다 void Div_Rem(int a, int b, int div, int rem) { div = a/b; rem = a%b } int main() { int div=0; int rem=0; Div_Rem(23,5, div, rem); cout<<“23 = 5*“<<div<<“+”<<rem<<“\n”; return 0; }
포인터 변수를 인자로 전달하기(1) • 나누기를 하여 몫과 나머지를 구한다 void Div_Rem(int a, int b, int * pdiv, int * prem) { * pdiv = a/b; * prem = a%b } int main() { int div=0; int rem=0; Div_Rem(23,5, &div, &rem); cout<<“23 = 5*“<<div<<“+”<<rem<<“\n”; return 0; }
포인터 변수를 인자로 전달하기(2) • 포인터 타입의 인자를 사용해서 함수의 결과 값을 얻어오는 방법의 정리 • 함수의 매개 변수는 포인터 타입으로 정의한다. • 인자를 넘겨줄 때는 결과 값을 담고 싶은 변수의 주소를 넘겨준다. • 함수 안에서 결과를 넘겨줄 때는 매개변수가 가리키는 곳에 값을 넣어준다.
레퍼런스 변수를 인자로 전달하기(1) • 레퍼런스 변수를 사용해서 함수 밖으로 결과를 전달 void Div_Rem(int a, int b, int& rdiv, int& rrem) { rdiv = a/b; rrem = a%b } int main() { int div=0; int rem=0; Div_Rem(23,5, div, rem); cout<<“23 = 5*“<<div<<“+”<<rem<<“\n”; return 0; }
레퍼런스 변수를 인자로 전달하기(2) • 레퍼런스 타입의 인자를 사용해서 함수의 결과 값을 얻어오는 방법의 정리 • 함수의 매개 변수는 레퍼런스 타입으로 정의한다. • 인자를 넘겨줄 때는 결과 값을 담고 싶은 변수를 그대로 넘겨준다. • 함수 안에서 결과를 넘겨줄 때는 매개 변수에 값을 넣어준다.
배열을 인자로 전달하기(1) • 배열 타입의 인자는 실제로는 포인터를 사용해서 전달된다. int main() { char array[20] = "Hello, World!"; UsingArray( array); cout << "In main() : " << array << "\n"; return 0; } void UsingArray(char arr[] ) { cout << "In UsingArray() : " << arr << "\n"; arr[12] = '?'; }
배열을 인자로 전달하기(2) • 배열을 인자로 전달하는 방법의 정리 • 매개 변수의 타입을 적어줄 때 ‘배열의 원소 개수’는 적지 않는다. • 인자로 넘겨줄 때는 배열의 이름을 넘겨준다. • 인자로 넘어온 배열을 사용할 때는 그냥 평범한 배열을 사용하듯이 하면 된다.
const를 사용한 배열의 보호 • 인자에 const 속성을 부여해서 배열의 내용이 변경되는 것을 막을 수 있다. • UsingArray()가 호출될 때 실행되는 가상의 코드 void UsingArray( constchar arr[] ) { cout << "In UsingArray() : " << arr << "\n"; arr[12] = '?'; // Error } const char* arr = array;
2차원 배열의 전달 int main() { int array[5][3] = {{ 1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}, {13, 14, 15}}; Using2DArray( array); return 0; } void Using2DArray( int arr[][3] ) { for (int i = 0; i < 5; ++i) for (int j = 0; j < 3; ++ j) { cout<<"arr[" << i << “][" << j << "]”; cout<<“=“<< arr[i][j] << "\n"; } }
기본적인 구조체의 전달 • 두 점 사이의 거리 구하기 struct Point { int x, y; }; int main() { Point a = {0, 0}; Point b = {3, 4}; double dist_a_b = Distance(a, b); return 0; } double Distance(Point pt1, Point pt2) { // 두 점의 거리를 반환한다. (임시로 0을 반환) return 0.0f; }
기본적인 구조체의 전달 • 구조체 변수를 인자로 전달하는 예 struct Point { int x, y; }; int main() { Point a = {0, 0}; Point b = {3, 4}; double dist_a_b = Distance(a, b); return 0; } double Distance(Point pt1, Point pt2) { // 두 점의 거리를 반환한다. // (임시로 0을 반환) return 0.0f; } [그림 14-32]
구조체의 전달과 성능 문제(1) • 조금 전의 방식(Call-by-value)으로 구조체 변수를 전달한 경우에 발생하는 성능 문제 • 인자의 내용이 매개 변수에 복사되는 시간이 낭비된다. • 매개 변수의 크기가 커지므로 메모리가 낭비된다. • 레퍼런스 변수를 사용해서 넘기면 위의 문제를 해결할 수 있다. double Distance( Point& p1, Point& p2) { // 중간 생략 // return 0.0; }
구조체의 전달과 성능 문제(2) • 레퍼런스로 넘긴 경우에 인자의 값이 바뀔 염려가 있으므로 const 속성을 사용해서 인자를 보호할 필요가 있다. • 구조체 변수를 인자로 전달하는 방법의 정리 • 구조체를 인자로 넘겨줄 때는 레퍼런스를 사용하자. • 함수의 안쪽에서 구조체의 내용을 읽기만 한다면 const와 레퍼런스를 사용하자. double Distance( constPoint& p1, const Point& p2)
CRT 함수의 사용 #include <iostream> #include <cmath> using namespce std; // 중간 코드 생략 double Distance(const Point& p1, const Point& p2) { // 피타고라스의 정리를 사용한다. double distance; distance = sqrt( pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2) ); // 결과를 반환한다. return distance; } [그림 14-36]
오버로딩(Overloading) • 같은 이름의 함수들이지만 인자의 형태가 다른 경우 각각에 대해 할 일을 지정한다! 여러가지 다른 일 하나의 함수이름
오버로딩(Overloading) • 오버로딩을 사용해서 두 가지 버전의 max() 함수를 만드는 예 • 오버로딩을 사용할 수 없다면 서로 다른 이름의 함수를 만들어서 사용해야 한다. int max( int a, int b ); float max( float a, float b ); int max_i( int a, int b ); float max_f( float a, float b );
기본적인 오버로딩의 규칙 • 인자의 타입을 통해서 호출될 함수를 결정한다. int VariableReturnType( char c, int i ); // 1번 double VariableReturnType( char c, double d ); // 2번 ... VariableReturnType( ‘A’, 100 ); // 1번 함수 호출 VariableReturnType( ‘A’, 100.12 ); // 2번 함수 호출
기본적인 오버로딩의 규칙 • 반환 값만 틀린 경우는 오버로드 할 수 없다. • 인자가 다르더라도 오버로드 할 수 없는 경우 int VariableReturnType( char c, int i ); double VariableReturnType( char c, int i ); // Error ... VariableReturnType( ‘A’, 100 ); // 어느 것을 호출해야 할 지 모름 void SameSignature( int i ); void SameSignature( int& r ); ... int i = 10; SameSignature( i ); // 어느 것을 호출해야 할 지 모름
적당한 함수를 찾는 순서 • 오버로드 된 여러 버전의 함수 중에서 알맞은 함수를 찾는 순서 • 1. 정확하게 일치하는 경우(Exact Match) • 2. 승진에 의한 형변환(Promotion) • 3. 표준 형변환(Standard Conversions) • 4. 사용자에 의한 형변환(User-defined Conversions) void WhichOne( float f ); // 1순위 (exact match) void WhichOne( double d ); // 2순위 (promotion) void WhichOne( int c ); // 3순위 (standard conversions) int main() { WhichOne( 3.5f ); return 0; }
디폴트 인자 • 디폴트 인자를 사용하는 예 bool SetFramesPerSec(int fps = 10) { // 코드 생략 return true; } int main() { // 인자 없이 함수를 호출한다. SetFramesPerSec(); return 0; }
디폴트 인자를 사용하는 규칙 • 디폴트 인자들은 오른쪽 끝에 모여 있어야 한다. // 올바름: 디폴트 인자 c는 오른쪽에 있다. void DefaultArgs2( int a, int b, int c = 3 ); // 올바름: 디폴트 인자 b, c는 오른쪽에 모여있다. void DefaultArgs1( int a, int b = 2, int c = 3 ); // 틀림: void DefaultArgs3( int a = 1, int b = 2, int c ); void DefaultArgs4( int a = 1, int b, intc = 3 ); void DefulatArgs5( int a = 1, int b, int c);
디폴트 인자를 사용하는 규칙 • 오버로딩과 디폴트 인자의 충돌하는 경우를 주의해야 한다. void Ambiguous( int a, int b = 100 ); // 1번 void Ambiguous( int a ); // 2번 ... Ambiguous( 50 ); // 어느 것?
재귀 호출(Recursion)(1) • 자기가 자신을 호출하는 것
재귀 호출(Recursion)(1) • 재귀호출의 예 • void RecursiveCall() • { • RecursiveCall(); • } • int main() • { • RecursiveCall(); • }
재귀 호출(Recursion)(2) • 재귀호출의 예 • void WhildPositive(int n) • { • cout<<n<<“\n”; • if(n<0) return; • WhilePositive(n-1); • } • int main() • { • WhildPositive(int n) • }
재귀 호출(Recursion) 연습 • 재귀 호출을 사용해서 팩토리얼 값을 구하라 1! = 1 2! = 2*1! 3! = 3*2! 4! = 4*3! 5! = 5*4! … 1! = 1 2! = 2*1 3! = 3*2*1 4! = 4*3*2*1 5! = 5*4*3*2*1 …
재귀 호출(Recursion) 연습 • 재귀 호출을 사용해서 팩토리얼 값을 구하라 • int Factorial(int n) • { • if(n<=1) return 1; • return n*Fartorial(n-1); • } • int main() • { • Factorial(5); • }
함수 포인터 • 함수 포인터를 사용해서 함수를 가리키는 예 void Dog() { cout << "I'm a dog.\n"; } void Cat() { cout << "I'm a cat.\n"; } int main() { void (*p)(); p = &Dog; (*p)(); p = &Cat; (*p)(); return 0; } [15-10]
함수 포인터의 정의 • 함수 포인터 타입의 변수를 정의하는 방법