본문 바로가기
!?/C++

함수

by Where's my namespace 2012. 8. 11.

함수.

어떻게 사용하느냐에 따라서 무긍무진한 변화를 보인다.  그중에 함수의 중요 기능들만 살펴보자.

함수의 기본 형식은 간단하다.

반환값의형태 함수명 ( 시그니쳐)

말로보면 어려울수도 있으니 간단한 예제를 보자.

 

void print (int a) {

cout << "Hello~! " << "넘겨받은 정수는 : " << a << endl; 

}

 

위의 예제는 아주 기초적인 함수의 사용법을 나타냈다. 말로 풀어보자면, 반환값이 없는 함수 print 는 

시그니쳐( 인자) 로 정수하나를 받는다.  후에 함수의 작업을 수행한다.

 

위의 예제는 기초중에서도 매우 기초다.  함수를 잘 쓴다는건 어쩌면 프로그래밍의 능력이기 보다는 개개인의 예술적 감각과 비슷하지 않나 생각한다. 어떻게 쓰는게 더 보기 쉽고 간편한가 하는 문제는 프로그래밍전

고민해볼 필요가 있다. 

 

함수는 정말 사용에 따라 경우의 수가 많고 변화가 다양하다. 

함수의 인자로는 흔히 알고 있는 모든 변수와 포인터, 레퍼런스, 함수를 인자로 넘겨줄수 있다. 중요한 점은 인자로 넘겨주는 함수와 인자 변수의 명이 같다고 해서 그 변수가 같은 변수는 아니라는 점이다. 

예제를 살펴보자. 

 

void test( int a ) {

a = 10;

cout << "함수 안의 변수 : " << a << endl;

}

int main ( ) {

int a = 0 ; 

test(a);

cout << "함수 밖의 변수 : " << a << endl;

return 0;

}

 

위의 코드를 살펴보자. 함수 test 는 시그니쳐로 정수하나를 받고 있다.  메인함수 내에도 test 시그니쳐와 똑같은 변수명을 가진 정수 a 가 있고,  변수 a 를 함수 test에 넘겨준다. 함수 내용을 수행한다.

그럼 최종족으로 출력되는 변수 a의 값은 몇일까?

답은 0 이다. 함수에서 인자로 받아서 변화를 준다고 해도 그 변수 자체가 변하는건 아니다. 만약 변수의 값이

바뀌길 원했다면, 레퍼런스나 포인터를 사용해서 바꾸면 바꿀수 있다.

 

하지만 여기서도 예외가 있다. 바로 인자로 배열을 넘겨줄때는 얘기가 달라진다.

위의 코드를 배열을 인자로 넘겨주게 고쳐보자.

 

void test( int a[] ) {

a[0] = 1;

cout << "함수 안의 변수 : " << a[0] << endl;

}

int main ( ) {

int a[5] = {0} ;

test(a);

cout << "함수 밖의 변수 : " << a[0] << endl;

return 0;

}

이럴 경우 a[0] 의 값을 얼마가 출력될까? 답은 1 이다.

이유는 간단하다. 배열을 함수에 전달할때 배열의 포인터를 전달해준다. 만약 이렇게 전달해 주지 않는다면 함수는 배번 배열을 받아서 그 배열과 똑같은 크기의 배열을 만들고 배열의 내용을 모조리 복사해 주는 일을 매번 해야될 것 이다. 위의 경우에서 배열의 값이 바뀌는게 싫고, 단순 읽기용으로 쓸려면 const 타입으로 설정해버리면 된다.

 

void test(const int a[] ) {

cout << "함수 안의 변수 : " << a[0] << endl;

}

 

이럴 경우 함수 안에서 배열의 원소를 고치면 오류가 난다.

 

C++에서 함수는 오버로딩(overloading) 이 가능하다.  오버로딩이 무엇인가? 같은 이름을 가진 함수를 사용할 수있는 것이다. 이경우에 몇가지 규칙이 있다.

우선 사용법을 알아보자.

 

int test(int a) ;

float test(float a) ;

doulble test(double a);

 

C의 경우라는 위의 경우는 오류가 난다. 하지만 C++에서는 가능하다. 여기에서 중요한 규칙이있다. 함수의 오버로딩을 사용 할때는 각 함수의 시그니쳐가 달라야한다는 것이다.

예로 들면

 

int test (int a)

float test (int a)

 

의 경우 반환값이 다르더라도 시그니쳐가 완전히 같기 때문에 컴퓨터가 어떤 함수를 사용할지 인식을 못하게 된다. 결과적으로 오류가 난다.

다른 경우지만 시그니쳐가 다르더라고 함수를 호출 하는 경우도 있다.

 

float test( float a);

float test(char a);

 

이 두 경우,  메인에서 test(10); 을 호출했다면 어떤 함수가 호출될까. 정답은 float test(float a) 함수가 호출된다.

이는 승진 형변환으로 int 형에서 float 형으로 형변환이 일어나면서 float test(float a) 함수가 호출되게 된다.

그렇다면 함수 오버로딩의 경우 호출 조건의 순위는 무엇일까.

 

1. 완벽한 일치.

2. 승진 형변환

3. 표준 형변환

4. 사용자에 의한 형변환

 

순으로 오버로딩된 함수의 호출 순위를 결정하게 된다. 위 사항들만 주의해서 쓴다면 깔끔한 오버로딩되니 함수를 사용할수 있을 것 이다.

 

함수의 경우 디폴드인자 라는 것이있다.  디폴트 인자란, 함수를 사용할때 인자의 값을 넘겨주지 않은 경우, 함수에서 기본적으로 설정해둔 인자를 사용하는 것을 말한다.

예제를 보자.

void test ( int a , int b = 10) ;

위의 예제에서 b 변수에 기본값으로 10을 주었다.  만약 함수를 호출할때 test(10 ) 과 같은 경우로 호출 한다면 b는 기본값인 10으로 사용 될것이다.  디폴트 인자에서 주의할 점은 디폴트 인자들은 항상 시그니쳐의 오른쪽에 모여 있어야 한다는 것이다.

예를들어

void test( int a = 10 , int b, int c = 10) 의 경우는 에러가 난다. 반드시 void test (int a, int b = 10, int c = 10) 으로 써야한다.

 

'!? > C++' 카테고리의 다른 글

동적메모리 할당  (0) 2012.08.11
함수의 포인터  (0) 2012.08.11
함수의 재귀호출  (0) 2012.08.11
c/c++ 의 꽃 포인터  (0) 2012.07.05
객체  (0) 2012.06.27