본문 바로가기
Develop/C++

[C ++] 다중 정의 (Overloading)

by J-rain 2023. 2. 2.

C++에서 '다중 정의'는 하나(함수 이름, 변수 이름등)가 여러 의미를 동시에 갖는 것을 말한다.

C와 달리 C++에서는 매개변수 구성이 달라지거나 어떤 식으로든 함수 원형이 달라지면 이름이 같더라도 전혀 다른 함수가 된다.

 

#include <iostream>
using namespace std;

int Add(int a, int b, int c)
{
  cout << "Add(int, int , int): ";
  
  return a + b + c;
  }
  
  int Add(int a, int b)
  {
   cout << "Add(int, int): ";
   
   return a + b;
   }
   
   int Add(double a, double b)
   {
    cout << "Add(double, double): ";
    
    return a + b;
    }
    
    int main(void)
    {
      cout << Add(3,4) << endl;       //11번행 호출
      cout << Add(3,4,5) << endl;     //4번행 호출
      cout << Add(3.14,1.59) << endl; //18번행 호출
      
      return 0;
     }

실행결과

  • 3과 4는 각각 int 자료형 상수이다. 따라서 27번행의 Add()함수는 11번행 함수를 호출한다.
  • 3.14와 1.59는 double 자료형 상수이다. 따라서 18번행 함수를 호출한다.
함수 다중 정의에서는 사용자 코드에 있는 함수 호출의 구체적인 대상이 무엇인지 식별하는 것이 중요하다.

 

C 함수 원형의 구성을 살펴보면

반환형식 호출규칙 함수이름(매개변수, 매개변수, ...)

크게 네가지 인데 이중 다중 정의에 영향을 주는것은 '매개변수'뿐이다.

 

1. 피호출자 함수 매개변수의 디폴트 값은 반드시 오른쪽 매개변수부터 기술해야 한다.

2. 매개변수가 여러 개일 때 왼쪽 첫 번째 매개변수의 디폴트 값을 기술하려면 나머지 오른쪽 '모든' 매개변수에 디폴트 값을 기술해야 한다.

3. 호출자 함수가 피호출자 함수 매개변수의 실인수를 기술하면 이는 왼쪽부터 짝을 맞추어 적용된다. 짝이 맞지 않는 매개변수는 디폴트 값을 적용한다.

 


Exemple

#include <iostream>
using namespace std;

void TestFunc(int a)
{
  cout << "TestFunc(int)" << endl;
}

void TestFunc(int a, int b = 10)
{
  cout << "TestFunc(int, int)" << endl;
}

int main(void)
{
TestFunc(5);

return 0;
}

실행결과를 보기전에 질문에 먼저 답해보자

  • 이 예제는 컴파일 가능한가? 즉, 오류가 없는가?
  • 오류가 발생한다면 몇 번 행에서 발생하는가?
  •  TestFunc() 함수의 다중 정의가 문제인가? 아니면 호출하는 쪽이 문제인가?

 

 

 

실행결과

예제를 빌드하면 컴파일 오류가 발생하는데, 오류 내용에 아예 'ambiguous' 모호하다는 표현이 있다. 

16번행을 주석문으로 처리하거나 TestFunc(5,10)과 같이 int 자료형 실인수 두 개를 기술하면 오류는 사라진다.

즉, TestFunc() 함수가 다중 정의되는 것은 문법적으로 문제가 아니라는 것이다.

 

 

다중 정의를 통하여 함수를 만든 제작자는 오류를 경험하지 않지만 함수 사용자는 오류를 경험할 수 있다.

멤버 함수 다중 정의

#include <iostream>
using namespace std;

class Rain
{
 public:
   Rain() : Data(0) { };
   
   int GetData(void) { return Data; }
   void SetData(int Param) { Data = Param ;}
   
   // 매개변수가 double 자료형인 경우로 다중 정의했다.
   void SetData(double Param2) { Data = Param2; }
   
 private:
   int Data;
};

int main(void)
{
  Rain r;
  
  // Rain::SetData(int) 메서드가 호출된다.
  r.SetData(10);
  cout << r.GetData() << endl;
  
  Rain rr;
  
  // Rain::SetData(double) 메서드가 호출된다.
  rr.SetData(5.5);
  cout << rr.GetData() << endl;
  
  return 0;
}

실행결과

10 과 5.5가 아닌 5가 출력되었다.

GetData() 메서드의 반환 형식은 int 이다. 무엇보다 Rain 클래스는 정보를 저장할 목적의 멤버 변수를 하나 가지고 있는데 int 자료형인 Data이다. 이것만 보더라도 Rain은 처음부터 double 자료형을 지원할 수가 없다. 그런데 문제는 사용자가 SetData(int) 함수를 double 자료형 실인수로 호출할 수도 있다는 점이다.

따라서 잘못된 사용을 방지하기 위하여 delete 예약어를 적용해 명시적으로 메서드를 삭제할 수 있다.
13번행을  void SetData(double Param2) = delete; 로 바꾸게되면
컴파일 오류가 발생하여 사용자의 잘못된 사용을 원천 봉쇄 시킬 수 있다.

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

[C ++] 식별자 검색 순서  (0) 2023.02.02
[C ++] 템플릿(Template)  (1) 2023.02.02
[C ++] 범위 기반 for문  (0) 2023.02.02
[C ++] new와 delete연산자  (0) 2023.02.02
[C ++] auto  (0) 2023.02.02

댓글