[C++] C++ 함수와 네임스페이스

강민석·2022년 10월 18일
0

이것이 C++이다

목록 보기
1/8
post-thumbnail

2.1 디폴트 매개변수

  • cpp에서는 함수의 매개변수에 기본(디폴트)값을 지정할 수 있다.
  • 매개변수의 디폴트 값은 반드시 함수 원형의 선언 부분에 기술해야 한다.
  • 매개변수가 두 개 이상일 경우, 피호출자 함수 매개변수의 왼쪽부터 짝을 맞춘다.
    • 따라서, 피호출자 함수 매개변수의 디폴트 값은 반드시 오른쪽 매개변수부터 기술해야 한다.
#include <iostream>

int Example1(int param = 10) {
    int result = param * 2;
    return result;
}

// 함수의 선언부
// 선언부에서는 매개변수의 이름을 생략할 수 있다.
int Example2(int = 10);

int Example2(int param) {
    int result = param * 2;
    return result;
}

// 매개변수가 두 개일 경우
int Example3(int param1, int param2 = 10) {
    int result = param1 * param2;
    return result;
}

// 매개변수가 네 개일 경우
int Example4(int param1, int param2, int param3 = 10, int param4 = 10) {
    int result = param1 * param2 * param3 * param4;
    return result
}

int main(int argc, char* argv[]) {
    std::cout << Example1() << std::endl;
    std::cout << Example1(10) << std::endl;

    std::cout << Example2() << std::endl;
    std::cout << Example2(10) << std::endl;

    std::cout << Example3(10) << std::endl;
    std::cout << Example3(10, 5) << std::endl;

    std::cout << Example4(10, 20) << std::endl;
    std::cout << Example4(10, 20, 30) << std::endl;
    std::cout << Example4(10, 20, 30, 40) << std::endl;

    return 0;
}
  • C++에서는 호출자의 코드만 보고 함수 원형을 확정해서는 안 된다!

2.2 함수 다중 정의

  • cpp에서는 함수 원형이 달라지면 이름이 같아도 서로 다른 함수로 인식한다.
  • 이를 통해 함수의 '다형성'을 지원한다.

2.2.1 다중 정의 일반

  • cpp의 함수 원형의 구성은 크게 네 가지(반환 형식, 호출 규칙, 함수 이름, 매개변수 구성)이다.
  • 함수 다중 구성에서 함수 이름은 이미 동일하다고 가정하므로, 다음 두 경우에는 다중 구성을 지원하지 않는다.
    • 반환 형식만 다른 경우
    • 호출 규칙만 다른 경우

2.2.2 다중 정의와 모호성

  • 디폴트 매개변수와 다중 정의가 조합되면 '모호성'이 발생할 수 있다.
  • '모호성'에 의해 컴파일러가 오류를 발생하는 시점은 '함수를 호출 할 때'이다.
    • 함수의 선언부에서는 오류가 발생하지 않는다.

"모호성에 의해 문제가 발생할 여지가 있다."보다는
"함수의 오버로딩을 다중 정의와 디폴트 값을 사용해 구현할 수 있으며, 둘은 양립할 수 없다."로 기억하는게 좋지 않을까? 그냥 내 생각임..

2.2.3 함수 템플릿

  • 메모리 낭비 및 유지보수 측면에서의 문제점 등을 고려했을 때, 함수 다중 정의보다는 '함수 템플릿'을 사용하는 것이 권장된다.
template <typename T>
반환형식 함수이름(매개변수) {
    수행 작업
}

// 호출부
함수이름<타입>(매개변수);
or
함수이름(매개변수);

그냥 제네릭이라고 이해하면 될것같다.
타입이 특정 연산을 지원하지 경우에는 어떻게 대응할 수 있는가?

2.3 인라인 함수

  • 함수를 호출하면 스택 메모리 사용이 증가하고 매개변수 때문에 메모리 복사가 일어나며, 제어 흐름도 이동해야 한다.
  • 단순히 함수를 호출하는 것만으로도 내부적으로 여러 연산이 일어나게 된다.
  • 길이가 짧고 단순한 함수일수록 함수를 호출하는 것만으로도 성능상에 안좋은 영향을 미치게 된다.
  • 컴파일러는 인라인 함수를 컴파일 할 때, 위의 연산을 생락하고 함수 내부의 작업을 '인라인'으로 실행되는 것으로 간주한다.
  • 따라서 인라인 함수를 사용하면 성능상으로 크게 이득이 될 수 있다.
  • 코드의 길이가 일정 수준 이상 길어지면 인라인 함수로써 사용되는 것은 바람직하지 않다.
  • 자동 최적화를 통해 일정 길이 미만의 함수는 인라인 함수로 컴파일되게끔 할 수 있다.(vscode)

2.4 네임스페이스

  • 네임스페이스는 cpp가 지원하는 각종 요소들(변수, 함수, 클래스 등)을 한 범주로 묶어주기 위한 문법이다.

2.4.1 네임스페이스

namespace 이름
{
    // 네임스페이스의 시작

    ~~~

    // 네임스페이스의 끝
}
#include <iostream>

namespace TEST {
    int num = 10;

    void addNum(int n = 0) {
        num += n;
    }
}

int main(int argc, char* argv[]) {
    std::cout << TEST::num << endl;
    std::cout << TEST::addNum(10) << endl;
    std::cout << TEST::num << endl;
    return 0;
}
  • 네임스페이스가 존재할 경우 식별자 앞에 범위 지정 연산자(::)를 이용해 네임스페이스를 기술할 수 있다.

2.4.2 using 선언

  • using 예약어를 통해 네임스페이스를 생략할 수 있다.
using namespace 네임스페이스이름;

2.4.3 네임스페이스 중첩

  • 네임스페이스 내부에 네임스페이스를 선언할 수 있다.

2.4.4 네임스페이스의 다중 정의

  • 서로 다른 네임스페이스에 선언된 함수 이름과 매개변수 구성이 같은 함수는 서로 다른 함수로 인식한다.

0개의 댓글