// 15-1 : 디폴트 인자의 사용
/*
책 내용이 좋으나 예제코드가 없어 여기에 적는다.
// 오버로딩
여러 함수들이 동일한 이름 사용할 수 있는 기능이다.
int max(int a, int b);
float max(float a, float b);
위를 보면 이름은 같으나, 반환값과 인자 타입이 다르다.
뭐가 좋은가?
타입이 바뀌더라도 max 함수 호출 코드는 바뀌지 않아서 좋다.
//기본적인 오버로딩 규칙
- 여러개 있을때 판별기준은 무엇인가?
컴퓨터가 인자의 타입을 확인해 가장 잘 어울리는 시그너치를 가진 함수를 호출한다.
- 반환값만 틀린 경우 오버로드 불가하다.
int Var(char c, int i);
double Var(char c, int i);
위 코드는 반환은 다르나, 시그니처 동일하다.
판단이 안되어서 오버로드 할 수 없다.
- 시그니처가 달라도 오버로드 불가한 경우.
void Same(int i);
void Same(int& r);
int i = 10;
Same(i);
위 두 함수 모두 이 방식으로 호출할 수 있어 컴퓨터가 판단이 안되어 오버로드 할 수 없다.
*/
bool SetFramesPerSec(int fps = 10)
{
// 코드 생략 (책에서 생략함)
return true;
}
int main()
{
SetFramesPerSec(); // 인자 없이 호출
return 0;
}
/*
--- 결과 ---
---
디폴트 인자 사용.
사용이 간단하다. 함수 원형에 매개변수 이름 뒤 디폴트 값 적으면 된다.
단, 몇가지 제한이 있다.
모든 디폴트 인자는 오른쪽 끝에 모여있어야한다.
*/
// 15-2 : 무작정 자기 자신 호출하는 함수
void RecursiveCall()
{
RecursiveCall();
}
int main()
{
RecursiveCall();
return 0;
}
/*
--- 결과 ---
---
재귀호출.
함수가 자기 자신을 호출한다.
수학적인 알고리즘에서 잘 등장하는 중요한 개념이다.
하지만 이 예제 잘못되었다. 무한히 반복하기 때문이다.
언제 끝나게 할 것인가?가 중요하다.
*/
// 15-3 : 재귀 호출 끝내기
#include <iostream>
using namespace std;
void WhilePositive(int n)
{
cout << n << "\n";
// 인자가 0보다 작으면 끝내기
if (n < 0)
return;
// 호출마다 -1 감소가 일어난다.
WhilePositive(n - 1);
cout << n << "\n";
}
int main()
{
WhilePositive(10);
return 0;
}
/*
--- 결과 ---
10
9
8
7
6
5
4
3
2
1
0
-1
0
1
2
3
4
5
6
7
8
9
10
---
*/
// 15-4 : 재귀 호출을 이용한 2진수로의 변환
#include <iostream>
using namespace std;
void Convert2Bin(int dec)
{
if (dec <= 0)
return;
Convert2Bin(dec / 2);
cout << dec % 2;
}
int main()
{
Convert2Bin(13);
cout << "\n";
return 0;
}
/*
--- 결과 ---
1101
---
재귀 호출 이용한 2진수로 변환.
10진수를 2진수로 바꾸었다.
현재 재귀함수는 정보가 점점 작아진다.
또한 결과들을 거꾸로 모은다.
이 특징을 이용하면 유용하다.
*/
// 15-5 : 함수의 포인터 기본
#include <iostream>
using namespace std;
// 원형이 동일한 두 개의 함수 정의.
void Dog()
{
cout << "Dog.\n";
}
void Cat()
{
cout << "Cat.\n";
}
int main()
{
void(*p)(); // 함수의 포인터 정의
p = &Dog; // 변수에 대한 포인터 사용과 크게 다르지 않다.
(*p)();
p = &Cat;
(*p)();
return 0;
}
/*
--- 결과 ---
Dog.
Cat.
---
함수의 포인터 기본.
포인터는 함수도 가리킬 수 있다.
이 포인터 사용하여 함수 호출 가능하다.
함수도 주소가 있다.
모든 정보는 메모리에 존재한다.
괄호고 *p 감싼 것은 우선순위 때문이다.
// typedef를 사용
함수의 포인터 정의를 간단하게 한다.
typedef를 사용하면 함수의 포인터 타입에 대한 별명을 만들 수 있다.
typedef void (*FN_TYPE2)(int);
위처럼 사용하면, 포인터 타입의 이름이 FN_TYPE2가 된다.
예를 들면,
int AnyName(int a, int b); 라면
typedef int (*FN_TYPE1) (int, int); 이다.
*/
// 15-6 : 자기 스스로 환경을 비교하는 경우
#include <iostream>
using namespace std;
void ForWindows9x();
void ForWindowsNT();
bool IsWindows9x();
void ImportantFunc();
int main()
{
ImportantFunc();
return 0;
}
void ForWindows9x()
{
cout << "9x\n";
}
void ForWindowsNT()
{
cout << "NT\n";
}
bool IsWindows9x()
{
return false;
}
void ImportantFunc()
{
// 현재 환경 검사 후 호출
if (IsWindows9x())
ForWindows9x();
else
ForWindowsNT();
// 생략
// 다시 호출
if (IsWindows9x())
ForWindows9x();
else
ForWindowsNT();
}
/*
--- 결과 ---
NT
NT
---
함수의 포인터를 다른 곳에 넘기는 방법 알아본다.
이 함수 필요할 때 호출하라고 넘겨주는 것이다.
A는 어떤 인자를 사용해 C 호출 모른다.
하지만 B는 알고 있다. 이럴 때 C를 넘긴다.
넘기지 않으면, 매번 실행 환경 검사 해서 함수를 호출해야한다.
그것이 예제 코드 내용이다.
*/
// 15-7 : 함수의 포인터를 사용한 개선
#include <iostream>
using namespace std;
// 9x나 NT 함수를 가리킬 수 있는 별명을 만든다.
typedef void (*SYSTEM_FUNC)();
void ForWindows9x();
void ForWindowsNT();
bool IsWindows9x();
void ImportantFunc(SYSTEM_FUNC pfnSyst);
int main()
{
SYSTEM_FUNC pfn;
if (IsWindows9x())
pfn = &ForWindows9x;
else
pfn = &ForWindowsNT;
ImportantFunc(pfn);
return 0;
}
void ForWindows9x()
{
cout << "9x\n";
}
void ForWindowsNT()
{
cout << "NT\n";
}
bool IsWindows9x()
{
return false;
}
void ImportantFunc(SYSTEM_FUNC pfnSyst)
{
(*pfnSyst)(); // 시스템 버전 감사가 없어졌다. 이미 호출해야 될 함수를 가리키고 있기 때문이다.
// 생략
(*pfnSyst)();
}
/*
--- 결과 ---
NT
NT
---
함수의 포인터를 사용한 개선.
함수와의 관계 파악 중요하다.
포인터를 주고, 필요할 때 호출하였다.
*/
'C++ > 뇌를 자극하는 C++' 카테고리의 다른 글
[C++] 챕터 17 - 문자열 : 문자의 배열 (0) | 2023.06.14 |
---|---|
[C++] 챕터 16 - 동적 메모리 할당 : 보다 자유로운 저장 공간 (0) | 2023.06.14 |
[C++] 챕터 14 - 함수 1 : 관련된 코드 모아담는 가방 (0) | 2023.06.14 |
[C++] 챕터 13 - 복합 타입 : 복합적인 정보 (0) | 2023.06.14 |
[C++] 챕터 12 - 배열과 구조체와 포인터 : 복합적인 방법으로 정보를 다루는 법 (0) | 2023.06.14 |
댓글