[ 5주차 - 1 ]
함수 : 참조, 중복, 디폴트 인수
1. 값에 의한 호출 ( call by value )
- 인수의 값을 함수의 형식 매개변수로 복사
- 함수의 매개변수 변화는 호출한 함수의 인수에게 영향을 주지 않음
→ 인수와 매개변수 사이에는 인수의 값이 매개변수에 복사되는 것 이외에는 서로 아무런 연관성이 없다.
#include <iostream>
using namespace std;
int sqr_it(int x);
int main() {
int t = 10;
cout << sqr_it(t) << ' ' << t;
return 0;
}
int sqr_it(int x) {
x = x * x;
return x;
}
//▶ 100 10
t에 10이 들어있어서 sqr_it 함수의 매개변수로 전달되어 x의 값이 100이어도 x 매개변수에 대응하는 인수인 t에
아무 영향을 주지 않는다. 값에 의한 호출이기 때문에 x에 100이라는 값이 저장이 되어도 t와는 무관하다.
2. 참조에 의한 호출 ( call by reference )
- 인수의 주소( 값이 아님 )를 매개변수로 복사
- 함수의 매개변수 변화는 호출한 함수의 인수에게 영향을 준다.
- 포인터 연산자를 사용 → 포인터를 함수에 전달하고 포인터 연산자를 사용해서 인수에 접근한다.
- 참조 매개변수를 사용 → 매개변수 앞에 &를 붙여서 선언한다.
ⓐ 포인터 연산자 사용하기 → 참조에 의한 호출로는 포인터 연산자를 이용함으로써 참조에 의한 호출을 직접 수행
#include <iostream>
using namespace std;
void swap(int *x, int *y);
int main() {
int i=10, j=20;
cout << "initial value i : " << i << " j : " << j << '\n';
swap(&j, &i); // i와 j의 주소로 swap()을 호출
cout << "swap value i : " << i << " j : " << j << '\n';
return 0;
}
void swap(int *x, int *y) {
int temp;
temp = *x;
*x = *y;
*y = temp;
}
// ▶ initial value i : 10 j : 20
// swap value i : 20 j : 10
ⓑ 참조 매개변수
#include <iostream>
using namespace std;
void f(int &i); // i가 참조 매개변수임을 의미
int main() {
int val = 1;
cout << "Old value for val : " << val << "\n";
f(val);
cout << "New value for val : " << val << "\n";
return 0;
}
void f(int &i) {
i = 10; // 함수 호출시 인수를 변경
}
// ▶ Old value for val : 1
// New value for val : 10
f(val)를 호출하면 val 변수의 주소가 i에 전달이 되고, i=10이라면 10을 i에 저장하는 것이 된다.
포인터 연산자 없이 i=10을 하면은 실제로 10은 i에 저장되는 것이 아니라 val 변수에 저장이 된다.
그래서 처음에는 val이 1을 가지고 있었지만 나중에는 10을 갖게 된다.
참조 매개변수를 선언하고 그 매개변수에 값의 변화를 준다면 바로 인수에 영향을 준다.
침조 매개변수를 사용한다면 포인터 연산자 사용 없이 참조에 의한 호출을 수행할 수 있다.
* 참조 매개변수 선언하기
ⓐ &는 변수 이름이 아닌 자료형과 연관
ex) swap( int& x, int& y ) == swap( int &x, int &y )
int* p == int *p
ⓑ int* a,b; → a는 정수형 포인터, b는 정수형 포인터가 아닌 정수형 변수
( *는 가장 가까이 있는 변수 하나에만 영향을 미친다. )
ⓒ 참조 매개변수를 사용한 swap 함수 구현하기
#include <iostream>
using namespace std;
void swap(int &x, int &y);
int main() {
int i = 10, j = 20;
cout << "initial value i : " << i << " j : " << j << '\n';
swap(i, j); // 변수 이름만 선언
cout << "swap value i : " << i << " j : " << j << '\n';
return 0;
}
void swap(int &x, int &y) { // 참조 매개변수
int temp;
temp = x;
x = y;
y = temp;
}
// ▶ initial value i : 10 j : 20
// swap value i : 20 j : 10
* 참조 매개변수는 C++ 부터 도입한 개념이다.
* C++부터는 포인터 연산자보다 참조 매개변수를 사용해서 참조에 의한 호출을 한다.
3. 참조를 사용할 때의 제한점
- 참조 변수를 다시 참조할 수 없다.
- 참조 배열을 생성할 수 없다.
- 참조 변수에 대한 포인터를 생성할 수 없다. 즉 참조 변수에 & 연산자를 쓸 수 없다.
- 참조는 비트필드에 허용되지 않는다.
함수 중복 ( function overloading )
1. 둘 또는 그 이상의 함수가 매개변수 선언이 다르면 같은 이름을 공유할 수 있다.
2. 중복된 함수들 중 어느 함수를 호출할 것인지 결정하기 위해 컴파일러는 인수의 자료형 또는 개수를 사용한다.
3. 중복된 함수들 사이에 연관성이 있어야한다는 규칙은 없지만 어떠한 연관성이 있다.
#include <iostream>
using namespace std;
void f(int i);
void f(int i, int j);
void f(double k);
int main() {
f(10);
f(10, 20);
f(12.24);
return 0;
}
void f(int i) {
cout << "f(int) is " << i << "\n";
}
void f(int i, int j) {
cout << "f(int i, int j) is " << i << " " << j << "\n";
}
void f(double k) {
cout << "f(double k) is " << k << "\n";
}
// ▶f(int) is 10
// f(int i, int j) is 10 20
// f(double k) is 12.24
디폴트 함수 인수 ( default argument )
1. 매개변수에게 주어지는 디폴트 값
디폴트값 : 함수 호출시에 매개변수에 대응하는 인수가 명시되지 않을 때 자동으로 사용하는 값
ex) int func( int a, int b = 25 ) { ... }
2. 복잡한 함수에 대한 호출을 단순화 하기 위해 사용될 수 있다.
3. 함수 중복의 축약 형식( shorthand form )으로 사용될 수 있다.
4. 디폴트 인수 값을 가지는 함수 규칙
- 디폴트 값은 오직 한번만 명시되어야한다.
- 함수가 파일 내에서 선언되는 처음에 명시되어야만 한다.
- 디폴트 값을 취하는 매개변수를 정의하기 시작했다면, 디폴트 값을 갖지 않는 매개변수를 명시할 수 없다.
- 중복 함수의 다른 버전은 다른 디폴트 인수를 가질 수 있다.
void myfunc( double num = 0.0, char ch = 'X' ){
...
}
myfunc( 198.234, 'A' ); // 지정된 값을 전달
myfunc( 10.1 ); // num에는 값을 전달하고 ch는 디폴트 값을 사용
myfunc(); // num과 ch는 모든 디폴트 값을 사용한다.
#include <iostream>
using namespace std;
void clrscr(int size = 25); // 디폴트 값은 한번만 명시되고 파일내에서 선언되는 처음에 명시
int main() {
for (int i = 0; i < 30; i++) {
cout << i << "\n";
}
clrscr(); // 25줄을 지운다.
for (int i = 0; i < 30; i++) {
cout << i << "\n";
}
clrscr(10); //10줄을 지운다.
return 0;
}
void clrscr(int size) {
for (; size; size--) { //빈줄만 표시
cout << "\n";
}
}
함수 중복과 애매모호함
애매모호함( ambiguity ) : 정확히 중복된 함수의 두개 이상의 컴파일러가 어떤 것을 선택해야하는지 알 수 없는 상황
( 애매모호한 문장은 에러이며 컴파일 되지 않는다. )
#include <iostream>
using namespace std;
float myfunc(float i);
double myfunc(double i);
int main() {
cout << myfunc(10.1) << " ";
cout << myfunc(10) << " "; // float 형과 double 형 중 어느 것으로 변환해야할지 컴파일 에러
return 0;
}
float myfunc(float i) {
return i;
}
double myfunc(double i) {
return i;
}
실습문제
3개의 함수를 중복시키고 main 함수에서 호출해서 결과를 출력하는 프로그램 작성하기
int powers( int x ) // x^2반환
int powers( int x, int y ) // x^y반환
int powers( int x, int y, int z ) // x^y * z
// x^y를 구할 때 반복문을 사용
#include <iostream>
using namespace std;
int powers(int x);
int powers(int x, int y);
int powers(int x, int y, int z);
int main() {
cout << powers(5) << "\n";
cout << powers(5,2) << "\n";
cout << powers(5,5,4) << "\n";
return 0;
}
int powers(int x) {
return x * x;
}
int powers(int x, int y) {
int result = 1;
for (int i = 0; i < y; i++) {
result *= x;
}
return result;
}
int powers(int x, int y, int z) {
int result = 1;
for (int i = 0; i < y; i++) {
result *= x;
}
return result * z;
}
#include <iostream>
#include <cmath>
using namespace std;
int powers(int x);
int powers(int x, int y);
int powers(int x, int y, int z);
int main() {
cout << powers(5) << "\n";
cout << powers(5, 2) << "\n";
cout << powers(5, 5, 4) << "\n";
return 0;
}
int powers(int x) {
return pow(x,2); //pow함수는 n 제곱을 구할 수 있음
}
int powers(int x, int y) {
return pow(x,y);
}
int powers(int x, int y, int z) {
return pow(x, y) * z;
}
cmath 라이브러리에 pow 함수를 사용하면 쉽게 n 제곱을 구할 수 있다.
sqrt(n) : 제곱근
cbrt(n) : 세제곱근
hypot( a,b ) : 두 수를 제곱하고 더한 값의 제곱근
'2CHAECHAE 학교생활 > 객체지향프로그래밍(C++)' 카테고리의 다른 글
[ 객체지향프로그래밍(C++) 6주차 ① ] (0) | 2022.04.11 |
---|---|
[ 객체지향프로그래밍(C++) 5주차 ② ] (0) | 2022.04.01 |
[ 객체지향프로그래밍(C++) 4주차 ② ] (0) | 2022.03.28 |
[ 객체지향프로그래밍(C++) 4주차 ① ] (0) | 2022.03.24 |
[ 객체지향프로그래밍(C++) 3주차 ② ] (0) | 2022.03.21 |