icon안동민 개발노트

함수 오버로딩


함수 오버로딩 개요

 함수 오버로딩은 같은 이름의 함수를 여러 개 정의할 수 있게 해주는 C++의 강력한 기능입니다. 이는 매개변수의 타입이나 개수가 다른 경우에 가능합니다. 함수 오버로딩을 통해 프로그래머는 직관적인 함수 이름을 유지하면서도 다양한 타입에 대해 작업할 수 있습니다.

함수 오버로딩의 기본 원리

 다음은 함수 오버로딩의 간단한 예시입니다.

#include <iostream>
 
int add(int a, int b) {
    std::cout << "Adding integers: " << a << " + " << b << std::endl;
    return a + b;
}
 
double add(double a, double b) {
    std::cout << "Adding doubles: " << a << " + " << b << std::endl;
    return a + b;
}
 
int main() {
    std::cout << add(5, 3) << std::endl;      // int 버전 호출
    std::cout << add(3.14, 2.5) << std::endl; // double 버전 호출
    return 0;
}

 이 예제에서 add 함수는 정수와 실수에 대해 각각 다르게 정의되어 있습니다.

함수 오버로딩의 장점

  1. 직관적인 함수 이름 사용 : 같은 동작을 하는 함수들에 대해 일관된 이름을 사용할 수 있습니다.
  2. 타입에 따른 적절한 구현 : 각 타입에 최적화된 구현을 제공할 수 있습니다.
  3. 코드의 가독성 향상 : 함수의 목적이 명확해지고, 사용하기 쉬워집니다.
  4. 타입 안전성 : 컴파일러가 적절한 함수를 선택하므로 타입 관련 오류를 줄일 수 있습니다.

함수 오버로딩 해결 과정

 컴파일러는 다음 순서로 함수 호출을 해결합니다.

  1. 정확한 타입 일치
  2. 승격 (예 : charint, floatdouble)
  3. 표준 변환 (예 : intdouble, doubleint)
  4. 사용자 정의 변환
예시
#include <iostream>
 
void print(int i) {
    std::cout << "Integer: " << i << std::endl;
}
 
void print(double d) {
    std::cout << "Double: " << d << std::endl;
}
 
int main() {
    print(5);    // print(int) 호출
    print(3.14); // print(double) 호출
    print('A');  // print(int) 호출 (char가 int로 승격)
    return 0;
}

오버로딩 주의사항

  1. 반환 타입만 다른 경우 오버로딩 불가
int getValue();
double getValue(); // 컴파일 오류!
  1. 모호한 호출 피하기
void print(int i, double d) { /*...*/ }
void print(double d, int i) { /*...*/ }
 
print(1, 1); // 모호한 호출, 컴파일 오류!
  1. 기본 매개변수와의 상호작용
void display(int i) { /*...*/ }
void display(int i, int j = 0) { /*...*/ }
 
display(10); // 모호한 호출, 컴파일 오류!

함수 템플릿과 오버로딩

 함수 템플릿과 일반 함수를 함께 사용할 때, 컴파일러는 가장 특수화된 버전을 선택합니다.

#include <iostream>
#include <string>
 
template <typename T>
void print(T value) {
    std::cout << "Template: " << value << std::endl;
}
 
void print(int value) {
    std::cout << "Specialized for int: " << value << std::endl;
}
 
int main() {
    print(5);       // int 특수화 버전 호출
    print(3.14);    // 템플릿 버전 호출
    print("Hello"); // 템플릿 버전 호출
    return 0;
}

연산자 오버로딩 소개

 함수 오버로딩의 개념은 연산자에도 적용될 수 있습니다.

#include <iostream>
 
class Complex {
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
 
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
 
    void display() const {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
 
private:
    double real, imag;
};
 
int main() {
    Complex c1(3, 2), c2(1, 7);
    Complex result = c1 + c2;
    result.display(); // 출력: 4 + 9i
    return 0;
}

연습 문제

  1. 정수, 실수, 문자열을 인자로 받아 각각의 타입에 맞는 출력을 하는 print 함수를 오버로딩하여 구현하세요.
  2. 2차원 및 3차원 좌표를 표현하는 Point2DPoint3D 클래스를 만들고, + 연산자를 오버로딩하여 좌표의 덧셈을 구현하세요.


참고 자료