C++ 함수 오버로딩(Function Overloading)

프로그래밍/C++ 2019.08.19 댓글 Plorence

함수 오버로딩(Function Overloading)

함수 오버로딩도 디폴트 매개변수와 마찬가지로 C++에 새로 추가된 기능입니다.
디폴트 매개변수는 개수를 다르게 사용함으로써 같은 함수를 호출할 수 있게 합니다.
반면 함수 오버로딩은 서로 다른 여러 개의 함수가 하나의 이름을 공유하는 것입니다.
함수 오버로딩은 OOP 다형성의 구현입니다.
함수 오버로딩의 핵심은 함수의 매개변수 리스트, 함수 시그니처(function signature)입니다.
함수 시그니처란 매개변수 개수, 데이터형, 순서에 대한 것입니다.

이때 반환형은 상관없습니다.

#include <iostream>
int func1(int num1 , int num2) {
    return num1 + num2;
}
int func2(int num1, int num2) {
    return num1 + num2;
}
int main(void) {
}

이때 func1과 func2의 매개변수는 개수, 데이터형, 순서가 똑같으므로 두 함수의 시그니처는 같습니다.

그러므로 위에 코드는 컴파일 에러가 발생합니다.

C++에서는 서로 다른 시그니처, 동일한 함수명이 함수 오버로딩입니다.

#include <iostream>
void display(int num1) {
    printf("%d",num1);
}
void display(char arr[]) { //함수 오버로딩!
    printf("%s", arr);
}
int main(void) {
}

함수의 이름은 동일하지만 시그니처는 다르므로 오버로딩이 문제없이 됩니다.

함수 오버로딩 후에 함수 호출을 하면 인자로 넘겨준 데이터형과 오버로딩된 것 중에 일치하는 게 있으면 컴파일 에러가 없습니다.(알아서 찾아준다.)

#include <iostream>
void display(int num1) {
    printf("%d",num1);
}
void display(char arr[]) { //함수 오버로딩!
    printf("%s", arr);
}
void display(long num1) {
    printf("%d", num1);
}
int main(void) {
    display(1);
    display(1999.123);
    return 0;
}

display(1999.123);에서 컴파일 에러가 발생합니다.

왜냐하면 맞는 게 있긴 하지만 암묵적 형 변환이 가능한 게 1가지(int제외)가 있고, 동일한 정수형이기 때문에 모호해지기 때문입니다.

Visual Studio 2017에서 뜨는 에러

 

오버로딩에서 주의해야 할 점

참조

int & x, int x가 될 것 같지만, 안됩니다.

인자로 int형 변수를 넘겨주면 int & x의 함수를 호출할지 int x의 함수를 호출할지 모호해지기 때문입니다.

그래서 어떤 데이터형의 참조와 그 데이터형은 동일한 시그니처로 간주합니다.

 

const와 const 아닌 변수는 서로 다른 시그니처다.

const 변수에는 const매개변수와 아닌 매개변수 둘 다 전달할 수 있지만, const가 아닌 변수에는 const가 아닌 매개 변수만 전달할 수 있기 때문입니다.

 

const 참조, rvalue 참조 매개변수는 또 다르다

참조에서 배운 거 그대롭니다.

 

이름 장식(Name Decoration)이란?

네임 맹글링(Name Mangling)이라고도 하며 이름 장식(name decoration)이라고도 합니다.

구글 기준으로 자료는 네임 맹글링으로 검색하여야 더 많이 나옵니다.

C++에서는 오버로딩된 함수를 어떻게 추적하냐면, 컴파일러는 함수의 정보(시그니처, 반환형, 함수명)를 가지고 암호화를 합니다.

암호화된 값을 가지고 추적을 합니다.

#include <iostream>
void display(int num1) { //!display@BNASXFA 대충 이런식으로..
    printf("%d",num1);
}
int main(void) {
    return 0;
}

당연히 함수의 정보가 다르면 암호화된 이름 장식도 다릅니다.

이름 장식은 함수의 정보가 같더라도 컴파일러가 다르면 다른 결과가 나옵니다.

 

컴파일러마다 이름장식 예

Compiler

void h(int)

void h(int, char)

void h(void)

Intel C++ 8.0 for Linux

_Z1hi

_Z1hic

_Z1hv

HP aC++ A.05.55 IA-64

_Z1hi

_Z1hic

_Z1hv

GNU GCC 3.x and 4.x

_Z1hi

_Z1hic

_Z1hv

HP aC++ A.03.45 PA-RISC

h__Fi

h__Fic

h__Fv

GNU GCC 2.9x

h__Fi

h__Fic

h__Fv

Microsoft VC++ v6/v7

?h@@YAXH@Z

?h@@YAXHD@Z

?h@@YAXXZ

Digital Mars C++

?h@@YAXH@Z

?h@@YAXHD@Z

?h@@YAXXZ

Borland C++ v3.1

@h$qi

@h$qizc

@h$qv

OpenVMS C++ V6.5 (ARM mode)

H__XI

H__XIC

H__XV

OpenVMS C++ V6.5 (ANSI mode)

CXX$__7H__FI0ARG51T

CXX$__7H__FIC26CDH77

CXX$__7H__FV2CB06E8

OpenVMS C++ X7.1 IA-64

CXX$_Z1HI2DSQ26A

CXX$_Z1HIC2NP3LI4

CXX$_Z1HV0BCA19V

SunPro CC

__1cBh6Fi_v_

__1cBh6Fic_v_

__1cBh6F_v_

Tru64 C++ V6.5 (ARM mode)

h__Xi

h__Xic

h__Xv

Tru64 C++ V6.5 (ANSI mode)

__7h__Fi

__7h__Fic

__7h__Fv

Watcom C++ 10.6

W?h$n(i)v

W?h$n(ia)v

W?h$n()

댓글