함수 오버로딩(overloading)은 동일한 이름을 가진 여러 함수를 서로 다른 시그니처(매개변수의 수 또는 유형)로 선언하는 메커니즘입니다.
매개변수에 대한 기본값은 함수 선언에서 지정할 수 있습니다. 미세한 점: 기본값은 함수 호출의 컴파일 시에만 고려되며, 보이는 시그니처에 따라 컴파일러가 지원합니다.
클래스에서 자주 있는 상황:
class Printer { void print(int n, char c = '*') { /* ... */ } void print(const std::string& s) { /* ... */ } }; Printer p; p.print(5); // print(int n, char c = '*')를 호출하며, c = '*' p.print("Hi"); // print(const std::string&)을 호출합니다.
미세한 점:
void foo(int x, int y = 10); void foo(int x); foo(1); // 오류: 어떤 함수를 호출할지 불분명함
클래스 멤버 함수에 대한 기본값을 지정할 수 있는 유일한 장소는 어디입니까?
답변: 클래스 메서드에 대한 기본값은 클래스 내에서 메서드를 선언할 때(또는 클래스 외부에서 첫 번째 선언에서) 지정할 수 있지만, 클래스와 구현 모두에서 지정하는 것은 허용되지 않습니다. 그렇지 않으면 재정의 오류가 발생합니다.
class X { void func(int x = 5); // 여기에서 가능 }; void X::func(int x) { /* ... */ } // 그러나 여기서는 안 됨!
이야기 1
은행 소프트웨어에서 컴파일 단계에서 오류가 발생했습니다: 서로 다른 기본값을 가진 일부 오버로딩된 함수가 적절한 선택을 방해하여, 컴파일 단계에서 호출이 모호해졌습니다 — 결과적으로 수동 수정이 이루어질 때까지 릴리스를 작성할 수 없었습니다.
이야기 2
팀에서는 모든 기본값을 클래스 헤더가 아닌 구현으로 가져가는 스타일이 퍼져 있었으나, 어떤 클래스의 메소드는 인터페이스와 구현 간의 불일치를 초래했습니다 — 서로 다른 모듈이 서로 다른 함수 매개변수를 보았고, 이는 이상한 컴파일 및 런타임 버그로 이어졌습니다.
이야기 3
공개 라이브러리를 확장하는 과정에서 동일한 매개변수가 있지만 다른 기본값을 가진 함수의 오버로딩을 잘못 추가했습니다. 컴파일러는 API 호출에 대한 모호성을 발생시켰고, 사용자는 구식 호출과 깨진 이진 호환성에 직면했습니다.