본문 바로가기
2CHAECHAE 학교생활/객체지향프로그래밍(C++)

[ 객체지향프로그래밍(C++) 5주차 ① ]

by 2CHAE._.EUN 2022. 4. 1.

[ 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 ) : 두 수를 제곱하고 더한 값의 제곱근