티스토리 뷰

디폴트 매개변수


디폴트 매개변수는 함수 호출에서 실제 매개변수를 생략했을 경우에 실제 매개변수 대신 사용되는 값입니다. 호출 시 매개변수의 개수가 다르더라도 결국 같은 함수를 호출하는 것입니다.

#include <iostream>
using namespace std;

int PLUS(int a, int b = 1) {
    return a + b;
}

int main() {
    int x = 5;
    int y = 7;
    cout << PLUS(x, y) << '\n'; // return 12
    cout << PLUS(x) << '\n'; // return 6
    cout << PLUS(y) << '\n'; // return 8
    return 0;
}

디폴트 매개변수를 통해 함수를 작성할 시, 디폴트 매개변수를 넣는 순서는 오른쪽에서 왼쪽 순서가 되어야 한다는 것입니다. 아래 코드는 각 함수의 원형을 제시합니다.

int allSum(int a, int b, int c = 1); // 맞다
int allSum2(int a, int b = 1, int c); // 디폴트 매개변수로 설정된 b 오른쪽에 설정이 되지 않은 c, 틀림
int allSum3(int a = 1, int b = 1,int c = 1);// 맞다

 

함수 오버로딩


같은 함수를 호출하는 디폴트 매개변수와는 달리, 함수 오버로딩은 서로 다른 여러 개의 함수가 이름을 공유하는 것입니 다. 이렇게 서로 다른 함수들을 구분하는 핵심은 각 함수의 매개변수 리스트입니다. 이를 함수 시그니쳐(function signature)라고 합니다. 여러 예시를 보며 각 시그니쳐가 구분되는지 살펴보겠습니다.

//Case #1: 매개변수 리스트가(int,int) (double,double)로 구분 되므로 서로 다른 시그니쳐
void print(int a, int b); 
void print(double a, double b);

//Case #2: 매개변수 리스트가 (int,float)으로 일치하므로 서로 같은 시그니쳐
double ACC(int c, float d);
int ACC(int c, float d);

//Case #3: 매개변수 리스트가 (int,float) (float,int) 로 구분되므로 서로 다른 시그니쳐
double foo(int c, float d);
double foo(float c, int d);

눈 여겨볼 경우는 2번 케이스입니다. return 타입이 다르니 서로 다른 시그니쳐라고 할 수 있지 않나?라고 생각할 수 도있지만 함수 오버로딩을 구분하는 것은 매개변수 리스트임을 상기하도록 합시다. 다음 경우도 살펴봅시다. 

// 매개변수가 다르니 서로 다른 시그니처인가?
double sq(double x);
double sq(double& x);

 

함수 오버로딩은 컴파일러 입장에서 살펴보아야 합니다. $sq$함수를 호출할 때 우리는 호출 함수에서 다음과 같이 작성할 것입니다.

double x = 5.0;
double ans = sq(x);

컴파일러 입장에선 위 두 가지 $sq$함수를 구분할 수 있는 방법이 없습니다. 그러므로 컴파일러가 함수 시그니처를 검사할 땐 어떤 데이터형에 대한 참조와 그 데이터형을 구분하지 않고 같은 시그니처로 간주합니다.

 

하지만 대응하는 함수를 찾는 과정에서 const와 const가 아닌 변수는 구분합니다.

#include <iostream>
using namespace std;

void Aoo(char* str); //#1
void Aoo(const char* str);//#2

void Boo(char* str); //#3

void Coo(const char* str); //#4

int main() {
    const char STR[20] = "Hello, world!";
    char* STR2 = "hello, wolrd!";

    Aoo(STR); // #2가 오버로딩된다.
    Aoo(STR2); // #1가 오버로딩된다.

    Boo(STR); // 대응하는 원형이 없다.
    
    Coo(STR2); // #4가 오버로딩된다.
    return 0;
}

const 변수와 const가 아닌 변수는 const를 사용한 매개변수에 값을 전달할 수 있지만, const 변수는 const를 사용하지 않은 매개변수에 값을 전달할 수 없다는 것에 유의하도록 합시다. 

 

void foo(double& d); // 변경가능한 lvalue와 매치
void foo(const double& d); //변경가능한 lvalue,const lvalue, rvalue와 매치
void foo(double&& d); //rvalue와 매치

마지막으로 살펴볼 참조 매개변수에서의 오버로딩입니다. 이 상황에서 foo를 오버로딩을 한다면 더 정확한 매치를 얻을 수 있습니다. 세 번째 $foo$함수가 없다면 호출 함수에서 $foo(i+j)$와 같은 호출은 2번째 $foo$를 오버로딩하여 사용합니다.

 

참고서적

Stephen Prata, 『C++ 기초플러스』, 성안당, 2012

'C++' 카테고리의 다른 글

[C++] namespace  (0) 2020.10.31
[C++] 함수의 사용  (0) 2020.10.24
[C++] 포인터  (0) 2020.10.17
[C++] 함수 템플릿  (0) 2020.10.04
[C++] inline 함수  (0) 2020.10.01
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함