Brise

[C++ 기본] 6. Function 본문

프로그램/C,C++

[C++ 기본] 6. Function

naudhizb 2022. 1. 15. 13:33
반응형
// C++함수의 특징 1. 디폴트 파라미터

// 주의 사항 1. 반드시 마지막 인자(오른쪽) 부터 차례대로
//                지정해야 한다.

// 주의 사항 2. 함수를 선언과 구현으로 분리할 경우 
//               선언부에만 표기한다. (28 page 아래)


void foo(int a = 0, int b, int c = 0); // error

void foo(int a  = 0, int b = 0 , int c = 0);

int main()
{
    foo(1, 2, 3);
//    foo(1, 2);
    //foo(1);
    //foo();
}

void foo(int a/* = 0*/, int b /*= 0*/, int c/* = 0 */)
{
}

C++은 멀티 패러다임 언어이기 때문에 OOP 적인 특징을 구현하고 있다. 때문에 함수에 대하여 default parameter를 지원한다. 인자를 생략하는 경우 기본값으로 입력되기 때문에 default parameter는 오른쪽에 지정되어야 한다.

#include <cstdio>
// 6_함수2 
// C++ 함수의 특징 2. 함수 오버로딩
// 인자의 갯수가 다르거나 인자의 타입이 다르면 동일한 이름의
// 함수를 2개이상 만들수 있다.
//#define SQUARE(x) ((x)*(x))
//SQUARE(++n);
int square(int a)
{
    return a * a;
}
double square(double a)
{
    return a * a;
}
int main()
{
    square(3);
    square(3.4);

    printf("%p\n", &square); // error
    printf("%p\n", (int(*)(int)) &square); // ok
}
// ok
void f1(int);
void f1(double);

// error. 반환타입만 다른 경우 오버로딩 안됨.
void f2(int);
int  f2(int);

// ok
void f3(int a);
void f3(int a, int b);

// error. 디폴트 값에 주의!
void f4(int a);
void f4(int a, int b = 0);

f4(5);

overloading을 사용하여 함수의 같은 이름의 함수, 같은 인자갯수의 함수에 인자 타입을 다르게 하여 함수의 입력에 따라 다른 함수로 접근할 수 있도록 할 수 있다.

같은 입력에 대하여 다른 output을 가지는 경우 매핑할 수 없으며, default parameter와 혼용시 결정이 어려운 경우가 있을 수 있으므로, 컴파일러 단게에서 오류를 발생시킨다.

// C++ 함수 특징 3. inline   .. 32page

// 인라인 함수 : 호출이 아니라 기계어 코드를 치환해 달라는의미
// 장점 : 빠르다.
// 단점 : 여러번 치환되면 목적코드(실행파일 크기)가 커질수 있다

       int add1(int a, int b) { return a + b; }
inline int add2(int a, int b) { return a + b; }
constexpr int add3(int a, int b) { return a + b; }

int main()
{
    int n1 = add1(1, 2);  // 호출
    int n2 = add2(1, 2);  // 치환
    int n3 = add3(1, 2);  // 컴파일 시간에 실행

    int arr[add3(1, 2)];
    arr[0] = 10;
}
// cl  6_함수3.cpp            => 실행파일 생성
// cl  6_함수3.cpp   /FAs    => 6_함수3.asm 생성
// cl  6_함수3.cpp   /FAs /Ob1

// /Ob1 : 인라인 치환을 적용해 달라.
// /FAs : 현재 C++ 소스의 어셈소스을 만들어달라
// /O2  : 속도를 위한 최적화 옵션


// notepad 6_함수3.asm   

실행시간 최적화를 위하여 inline함수, constexpr함수를 사용할 수 있다. inline의 경우 함수를 실행하나, 최적화 하여 실행하는 것이고, constexpr는 컴파일러가 함수를 실행하여 결과를 반영한다.

// 6_함수4
// C++ 함수의 특징 4. 함수 템플릿
/*
int square(int a)
{
    return a * a;
}
double square(double a)
{
    return a * a;
}
*/
/*
#define MAKE_SQUARE(T) T square(T a) { return a* a;}

MAKE_SQUARE(int)
MAKE_SQUARE(double)
*/

// 전처리기가 아닌 컴파일러에 의한 코드 생성

// 컴파일러에게 함수가 아닌 함수를 만드는 틀을 알려준다.
template<typename T> 
T square(T a)
{
    return a * a;
}

int main()
{
    square<int>(3);      // int square(int)함수 생성후. 호출
    square<double>(3.4); // double square(double)

    // 타입을 전달하지 않으면 함수 인자를 보고 타입을 결정한다
    square(3); //square<int>(3)
    square(3.4);

    printf("%p\n", &square); // error. square는 함수가 아니다
                            // 함수의 틀(template) 이다
    printf("%p\n", &square<int>); // square<int>가 함수이름
}
// 33 page

함수 overloading을 수행하기 위해서는 각 타입별로 함수를 코딩해주어야 한다. 이러한 불편함을 해소하기 위해서 template를 사용할 수 있다. template 선언 시 template 와 같이 선언할 수 있으며, function(arguments); 와 같이 사용할 수 있다. type을 생략하는 경우 인자의 타입에 따라 자동으로 타입이 정해진다. template함수는 컴파일 시에 코드가 생성되기 때문에 함수 이름 자체는 valid하지 않다.

  // 6_함수5
// C++ 함수 특징 5. 함수 삭제. C++11에서 추가된 기능
// 35 page

int add(int a, int b)
{
    return a + b;
}
// 36 page 아래 표
// 함수를 제공하지 않으면 : 인자의 암시적 변환에 의해서 
//                        동일이름의 다른함수 호출 가능

// 함수를 선언만 제공 : 사용했을때 link    에러 발생
// 함수를 삭제 할때   : 사용했을때 compile 에러 발생

//double add(double a, double b); // 핵심. 선언만 제공

double add(double a, double b) = delete; // C++11의 함수삭제
                                        // 문법
int main()
{
    add(1, 2);
    add(2.3, 3.2); // compile error. 삭제된 함수 사용
}

overloading을 통하여 다른 타입에 대하여 함수 진입을 지정할 수 있다면, C++11에서 추가된 기능을 이용하여 특정 타입으로 함수를 호출하는 경우 함수 호출에 대하여 오류를 호출할 수도 있다.

#include <iostream>

/*
// overloading resolution : 함수 찾는 순서
void foo(int n)    { std::cout << "int" << endl; }
void foo(short n)    { std::cout << "short" << endl; }

//void foo(float n)  { std::cout << "float" << endl; }
void foo(double n) { std::cout << "double" << endl; }
void foo(...)      { std::cout << "..." << endl; }
//template<typename T>
//void foo(T n)      { std::cout << "T" << endl; }

int main()
{
    float f = 3.4f;
    foo(f); // 1. exactly matching - float
            // 2. template 사용해서 float 버전 생성 - T
            // 3. promotion (데이타 손실이 없는 변환)
            //                        - double
            // 4. standard conversion(데이타 손실이 있어도
            //      float -> int 변환 가능 - int
            // 5. 마지막 선택이 가변인자
}

*/
void goo(int, int) {}        // 1
void goo(short, short) = delete;    // 2

int main()
{
    goo(1.3, 2.3); // 1을 선택할지 2를 선택할지 모른다는 에러

}  

진입 가능한 함수가 여러개인 경우 순서에 따라 어떤 함수로 실행할지 정하게 된다.

  1. exactly matching - float
  2. template 사용해서 float 버전 생성 - T
  3. promotion (데이타 손실이 없는 변환)
    - double
  4. standard conversion(데이타 손실이 있어도
    float -> int 변환 가능 - int
  5. 마지막 선택이 가변인자
// 6_함수7
// C++함수 특징6.  후위 반환 타입  37 page

// suffix return type( trailing return type)

//int square(int a)

auto square(int a) -> int   // C++11 부터 나온 새로운 함수 모양
{
    return a * a;
}
int main()
{
    square(3);
}

함수 선언 시 반환 타입에 대해서도 auto를 사용할 수 있다.

반응형

'프로그램 > C,C++' 카테고리의 다른 글

[C++ 기본] 9. 제어문  (0) 2022.01.29
[C++ 기본] 8. 반복문  (0) 2022.01.29
[C++ 기본] 7. template function  (0) 2022.01.16
[C++ 기본] 5. constexpr  (0) 2022.01.15
[C++ 기본] 4. Variable  (0) 2022.01.14
[C++ 기본] 3. 입출력  (0) 2022.01.14
[C++기본] 2. namespace  (0) 2022.01.14
Comments