함수 오버로드

일반적으로 함수 이름은 주요 용도를 반영하는 경향이 있습니다. 일반적으로 읽을 수 있는 프로그램에는 잘 선택된 다양한 식별자가 포함됩니다. 때로는 동일한 목적으로 서로 다른 함수가 사용될 수 있습니다. 예를 들어, 정밀도가 2배인 숫자와 같은 함수의 평균 값을 계산하지만 정수 배열을 사용하여 연산하는 함수를 고려해 보겠습니다. 둘 다 AverageFromArray라고 부르기에 편리합니다:

//+------------------------------------------------------------------+
//| double 유형의 배열에 대한 평균 계산                                 |
//+------------------------------------------------------------------+
double AverageFromArray(const double & array[],int size)
  {
   if(size<=0) return 0.0;
   double sum=0.0;
   double aver;
//---
   for(int i=0;i<size;i++)
     {
      sum+=array[i];    // double에 대한 합
    }
   aver=sum/size;       // 합계를 숫자로 나눔
//---
   Print("double 유형의 배열에 대한 평균 계산" );
   return aver;
  }
//+------------------------------------------------------------------+
//| int 유형의 배열에 대한 평균 계산                                     |
//+------------------------------------------------------------------+
double AverageFromArray(const int & array[],int size)
  {
   if(size<=0) return 0.0;
   double aver=0.0;
   int sum=0;
//---
   for(int i=0;i<size;i++)
     {
      sum+=array[i];     // int에 대한 합
    }
   aver=(double)sum/size;// double 타입의 양을 주고 나눕니다
//---
   Print("int 유형의 배열에 대한 평균 계산");
   return aver;
  }

각 함수에는 Print() 함수를 통한 메시지 출력이 포함됩니다;

   Print("int 유형의 배열에 대한 평균 계산");

컴파일러는 인수의 유형과 인수의 수량에 따라 필요한 함수를 선택합니다. 선택이 이루어지는 규칙을 서명 매칭 알고리즘이라고 합니다. 서명은 함수 선언에 사용되는 유형의 목록입니다.

예제:

//+------------------------------------------------------------------+
//| 스크립트 프로그램 시작 함수                                         |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int    a[5]={1,2,3,4,5};
   double b[5]={1.1,2.2,3.3,4.4,5.5};
   double int_aver=AverageFromArray(a,5);
   double double_aver=AverageFromArray(b,5);
   Print("int_aver = ",int_aver,"   double_aver = ",double_aver);
  }
//--- 스크립트 결과
// int 유형의 배열에 대한 평균 계산
// double 유형의 배열에 대한 평균 계산
// int_aver= 3.00000000    double_aver= 3.30000000

함수 오버로딩은 이름은 같지만 매개 변수는 다른 여러 함수를 만드는 프로세스입니다. 이는 오버로드된 함수 변형에서 인수 및/또는 인수 유형이 달라야 함을 의미합니다. 함수를 호출할 때 인수 목록과 함수 선언의 매개 변수 목록에 대한 대응 관계를 기반으로 특정 함수 변형이 선택됩니다.

오버로드된 함수를 호출할 때 컴파일러에는 적절한 함수를 선택하는 알고리즘이 있어야 합니다. 이 선택을 수행하는 알고리즘은 존재하는 유형의 캐스팅에 따라 달라집니다. 최고의 통신은 고유해야 합니다. 오버로드된 함수는 하나 이상의 인수에 대해 다른 모든 변형 중 가장 적합해야 합니다. 동시에 다른 변수가 아닌 모든 인수와 일치해야 합니다.

아래는 각 인수에 대한 일치 알고리즘입니다.

오버로드 함수 선택 알고리즘

  1. 가능한 경우 엄격 매칭을 사용합니다.
  2. 표준 유형 증가를 시도합니다.
  3. 표준 타입 캐스팅을 시도합니다.

다른 표준 변환보다 표준 유형 증가가 좋습니다. 증가는 floatdouble로, bool, char, short 또는 enumint로 변환하는 것입니다. 유사한 정수형 배열의 타입캐스팅도 타입캐스팅에 속합니다. 유사한 유형은 다음과 같습니다: bool, char, uchar 세 유형이 모두 싱글 바이트 정수이므로; double 바이트 정수 short와 ushort; 4바이트 정수 int, unit 및 color; long, ulong 및 datetime.

물론 엄격 매칭이 최고입니다. 이러한 일관성을 얻으려면 타입캐스팅을 사용할 수 있습니다. 컴파일러는 애매한 상황에 대처할 수 없습니다. 따라서 오버로드된 함수를 불명확하게 만드는 유형의 미묘한 차이와 암시적 변환에 의존해서는 안 됩니다.

의심스러운 경우 명시적 변환을 사용하여 엄격한 규정 준수를 보장하십시오.

MQL5에서 오버로드된 함수의 예는 ArrayInitialize() 함수의 예에서 볼 수 있습니다.

함수 오버로딩 규칙은 class method의 오버로드에 적용됩니다.

 

시스템 기능의 오버로딩은 허용되지만 컴파일러는 필요한 기능을 정확하게 선택할 수 있는지 확인해야 합니다. 예를 들어 시스템 함수 MathMax()를 4가지 방법으로 오버로드할 수 있지만 두 가지 변형만 맞습니다.

예제:

// 1. 오버로드 허용 - 함수가 파라미터 수에서 내장 MathMax() 함수와 다릅니다
double MathMax(double a,double b,double c);
 
// 2. 오버로드가 허용되지 않습니다!
// 매개 변수 수는 다르지만 마지막 값이 기본값입니다
// 이는 호출 시 시스템 기능을 숨기는 결과로 이어지며, 이는 허용되지 않습니다
double MathMax(double a,double b,double c=DBL_MIN);
 
// 3. 오버로드 허용 - 매개 변수 a 및 b 유형별 일반 오버로드
double MathMax(int a,int b);
 
// 4. 오버로드가 허용되지 않습니다!
// 파라미터의 수와 유형이 오리지날 double MathMax(double a, double b)와 동일합니다.
int MathMax(double a,double b);

더 보기

오버로드, 가상 함수, 다형성