함수중복
C++에서 함수 중복(Function Overloading)은 동일한 함수 이름을 가지고 다양한 매개변수 목록으로 정의하는 기술입니다. 함수 중복을 사용하면 동일한 이름의 함수를 호출하면서 다양한 데이터 유형이나 매개변수의 수를 처리할 수 있습니다. 컴파일러는 호출된 함수에 대한 적절한 버전을 선택합니다.
함수 중복의 주요 특징은 다음과 같습니다:
1. 동일한 함수 이름: 여러 버전의 함수 중복은 동일한 이름을 가집니다.
2. 매개변수 목록의 차이: 함수 중복은 매개변수의 수나 데이터 유형, 매개변수의 순서 등에서 차이가 있어야 합니다.
3. 리턴 유형은 중요하지 않음: 함수 중복에서 리턴 유형은 함수의 고유 식별자로 사용되지 않습니다.
예제:
#include <iostream>
// 정수형 매개변수를 받는 함수 중복
int add(int a, int b) {
return a + b;
}
// 실수형 매개변수를 받는 함수 중복
double add(double a, double b) {
return a + b;
}
int main() {
int sum1 = add(5, 3);
double sum2 = add(2.5, 3.7);
std::cout << "Sum1: " << sum1 << std::endl; // 출력: 8
std::cout << "Sum2: " << sum2 << std::endl; // 출력: 6.2
return 0;
}
위의 예제에서 `add` 함수는 두 가지 버전으로 오버로드되었습니다. 하나는 정수를 받고 다른 하나는 실수를 받습니다. 호출하는 함수에 따라 적절한 버전이 선택되어 실행됩니다.
함수 중복은 코드를 더 유연하고 가독성을 높이며, 비슷한 작업을 다양한 데이터 유형에 대해 수행하는 데 도움이 됩니다.
디폴트 매개 변수
C++에서 디폴트 매개 변수(Default Arguments)는 함수에 기본값을 가진 매개변수를 지정하는 기능입니다. 디폴트 매개 변수를 사용하면 함수를 호출할 때 일부 매개변수에 값을 제공하지 않아도 됩니다. 디폴트 매개 변수는 함수 시그니처에 기본값을 제공하는 방식으로 정의됩니다.
디폴트 매개 변수를 사용하려면 다음과 같은 규칙을 따라야 합니다:
1. 디폴트 매개 변수는 함수의 선언과 정의 중 하나에서 제공됩니다.
2. 디폴트 매개 변수는 오른쪽에서부터 왼쪽으로 순서대로 제공되어야 합니다. 즉, 마지막 매개변수부터 시작해서 순차적으로 디폴트 값을 제공합니다.
3. 함수를 호출할 때, 디폴트 매개 변수를 생략하면 해당 디폴트 값이 사용됩니다.
예제:
#include <iostream>
// 두 개의 정수 매개변수와 디폴트 매개 변수를 가진 함수
int add(int a, int b = 0) {
return a + b;
}
int main() {
int sum1 = add(5, 3); // 두 개의 매개변수를 전달
int sum2 = add(7); // 두 번째 매개변수 생략, 디폴트 값(0) 사용
std::cout << "Sum1: " << sum1 << std::endl; // 출력: 8
std::cout << "Sum2: " << sum2 << std::endl; // 출력: 7
return 0;
}
위의 예제에서 `add` 함수는 두 번째 매개변수에 디폴트 값 0을 가지고 있습니다. 첫 번째 호출에서는 두 개의 매개변수를 모두 전달하고, 두 번째 호출에서는 두 번째 매개변수를 생략하면 디폴트 값이 사용됩니다.
디폴트 매개 변수는 함수 인터페이스를 유지하면서 호출 코드를 더 간결하게 만들 수 있는 유용한 기능입니다.
함수 중복의 모호성
C++에서 함수 중복(overloading)을 사용할 때, 때로는 함수 호출이 모호하게 될 수 있습니다. 이러한 모호성은 컴파일러가 어떤 함수를 호출해야 하는지 결정하기 어려울 때 발생합니다. 함수 중복 모호성은 다음과 같은 상황에서 발생할 수 있습니다:
1. 매개변수의 수나 유형이 같은 경우: 여러 함수가 동일한 매개변수 수와 유형을 가지는 경우, 컴파일러는 어떤 함수를 호출해야 할지 판단하기 어려울 수 있습니다.
void foo(int x) { /* ... */ }
void foo(double y) { /* ... */ }
int main() {
foo(5); // 모호성 오류, int 또는 double을 받는 두 개의 함수가 있음
return 0;
}
2. 매개변수의 디폴트 값과 함수 중복: 디폴트 매개 변수를 사용하는 함수 중복의 경우, 인자를 생략한 호출이 모호성을 초래할 수 있습니다.
void bar(int x, int y = 0) { /* ... */ }
void bar(int x) { /* ... */ }
int main() {
bar(5); // 모호성 오류, 디폴트 매개 변수가 있는 함수 중복
return 0;
}
3. 상속과 함수 중복: 기본 클래스와 파생 클래스에서 함수 중복이 발생하는 경우, 상속 관계에서 모호성이 생길 수 있습니다.
class Base {
public:
void print(int x) { /* ... */ }
};
class Derived : public Base {
public:
void print(double y) { /* ... */ }
};
int main() {
Derived obj;
obj.print(5); // 모호성 오류, Base와 Derived 클래스에 동일한 이름의 함수가 있음
return 0;
}
모호성을 해결하기 위해서는 다음과 같은 방법을 사용할 수 있습니다:
1. 명시적 형변환: 호출할 함수의 매개변수 유형을 명시적으로 형변환하여 컴파일러에게 어떤 함수를 사용해야 하는지 알려줍니다.
foo(static_cast<int>(5)); // int 버전의 foo 호출
2. 함수 선언 수정: 함수 중복이 모호성을 일으키는 경우, 매개변수의 유형이나 개수를 수정하여 모호성을 해결할 수 있습니다.
3. using 지시어 사용: `using` 지시어를 사용하여 모호성을 해결할 수도 있습니다.
using Base::print;
obj.print(5); // Base 클래스의 print 함수 호출
함수 중복 모호성은 주로 프로그램이 복잡해질 때 발생하며, 주의해서 함수 선언과 호출을 조정하고 명시적 형변환을 사용하여 해결할 수 있습니다.
static 멤버
C++에서 `static` 멤버는 클래스의 모든 객체 간에 공유되는 멤버 변수 또는 멤버 함수를 나타냅니다. `static` 멤버는 클래스 자체에 속하며, 클래스의 모든 객체가 이를 공유하므로 각 객체의 별도의 인스턴스를 생성하지 않습니다. `static` 멤버는 클래스의 모든 인스턴스에서 동일한 값을 공유하거나 동일한 동작을 수행하는 데 사용됩니다.
1. 정적 멤버 변수 (Static Member Variables): 클래스 내에서 `static` 키워드를 사용하여 선언된 멤버 변수입니다. 모든 클래스 객체가 동일한 정적 멤버 변수를 공유하며, 객체의 개수와 관계없이 하나의 정적 변수만 존재합니다.
class MyClass {
public:
static int count; // 정적 멤버 변수 선언
};
int MyClass::count = 0; // 정적 멤버 변수 초기화
int main() {
MyClass obj1;
MyClass obj2;
MyClass::count++; // 정적 멤버 변수 증가
std::cout << MyClass::count << std::endl; // 출력: 2
return 0;
}
2. 정적 멤버 함수 (Static Member Functions): 클래스 내에서 `static` 키워드를 사용하여 선언된 멤버 함수입니다. 정적 멤버 함수는 객체의 인스턴스와 관련이 없으며, 클래스 자체와 관련된 작업을 수행합니다. 정적 멤버 함수는 클래스 이름을 사용하여 호출됩니다.
class MathUtility {
public:
static int add(int a, int b) {
return a + b;
}
};
int result = MathUtility::add(5, 3); // 정적 멤버 함수 호출
std::cout << result << std::endl; // 출력: 8
정적 멤버 변수 및 함수는 클래스의 인스턴스와 독립적으로 작동하며, 클래스의 모든 객체 간에 데이터 공유 또는 공통 기능을 제공하는 데 유용합니다. 또한 정적 멤버 변수는 객체 생성 없이 클래스 이름으로 직접 액세스할 수 있습니다.