IT공부/이것이 C++이다

C에서 C++ 문법 전환하기_2

doublehyun 2022. 3. 9. 02:03

Chapter.2 C++ 함수와 네임스페이스

  • 디폴트 매개변수
    • C에서는 함수를 호출하려 한다면 매개변수의 실 인수를 기술해야한다
    • C++에서는 매개변수의 초깃값을 설정해서 입력이 없을 경우 초깃값을 대입해 준다
      • 따라서 호출자를 보고 함수의 원형을 확정하면 안됨!!
      • ex) int TestFunc(int nParam = 10) // = int TestFunc(int = 10) 
      • 이때 함수 원형의 선언 부분에 기술해야하고, 정의 부분에 기술하면 컴파일 오류가 발생한다 // 선언부분 변수 이름 생략 가능
    • 매개변수 선언시 규칙
      1. 피호출자 함수 매개변수의 디폴트 값은 반드시 오른쪽 매개변수 부터 기술해야 한다
      2. 매개변수가 여려 개일 때 왼쪽 첫번째 매개변수의 디폴트 값을 기술하려면 나머지 오를쪽 모든 매개변수에 대한 디폴트 값을 기술해야 하며, 절대로 중간에 빼먹으면 안된다!
      3. 호출자 함수가 피호출자 함수 매개변수의 실인수를 기술하면 이는 왼쪽부터 짝을 맞추어 적용되며, 짝이 맞지 않은경우 매개변수는 디폴트 값을 적용한다
    • 모호성을 조심할 것, 가급적 디폴트 매개변수 사용을 지양할 것
  • 함수의 다중 정의
    • 다중정의, Overloading 은 함수의 다형성을 지원(편의성, 확장성)
      • 함수의 구성 요소 = 반환형식 호출규칙 함수이름(매개변수, 매개변수 ...);
    • 이때 다중정의, 오버로딩을 하기 위해선 매개변수를 제외한 모든 것은 동일해야 한다!!
    • 다중정의의 모호성
      • 다중정의와 디폴트 매개변수가 조합되면 '모호성'이 발생할 수 있다
        • ex) void TestF(int a) { ~ } / void testF(int a, int b = 10) { } 
        • 이때 TestF(5); 를 선언한다면 컴파일 오류가 발생한다( 모호성 때문)
    • 함수 템플릿(template)
      • 오버로딩으로 여러 함수를 만들기 보다 템플릿으로 만드는 것이 더 효율적이다
      • 템플릿은 일종의 '틀' / 함수를 찍어내기 위한 
        • ex) template <typename T> / T TestFunc(T a) { } // T는 자료형
        • 이때 testFunc을 호출하는 매개변수(실인수)의 자료형에 따라 T가 정해진다!
    • 인라인 함수(inline)
      • 인라인 함수 = (함수의 장점 + 매크로(#define) 의 장점) 이다
      • 함수의 원형 앞에 inline 예약어만 작성하면 된다
        • ex) inline int TestFunc(int a) { ~ }
      • 코드가 일정 수준 이상으로 길어지면 인라인 함수보다 그냥 함수가 더 효율적
      • 이는 컴파일러가 판단하여 인라인함수 <-> 일반 함수 로 바꿔서 컴파일 할 수 있다
    • 네임스페이스(namespace)
      • C++가 지원하는 각종 요소들(변수, 함수, 클래스 등)을 한 범주로 묶어주기 위한 문법
      • 소속, 구역 등으로 이해 (이름의 성 같은 존재)
        • 네임스페이스 선언 : namespace 이름 { ~ } // ~ 안에 변수, 함수, 클래스 가 들어갈 수 있다
        • 네임스페이스의 중복 선언이 가능하다 
        • 네임스페이스가 없는 함수는 '전역 네임스페이스'에 속한다
      • using 선언
        • namespace를 생략하기 위한 예약어
          • using namespace std; // std::cin 이라고 호출해야 했던 함수를 cin 으로도 호출할 수 있게 해줌
      • 같은 함수, 변수 등 이어도 namespace가 다르면 전혀 다른 개체로 인식된다
      • 네임스페이스와 다중정의
        • 다중 정의의 조건은 이름이 같아야 한다, 이때 이름이 같다는 것은 namespace도 같다는 뜻을 포함한다
        • 이름이 같고, 모든것이 같아도 namespace가 다르면 다른 개체! // 이때 호출시 네임스페이스를 구별해 주지 않으면 모호성에 의해 컴파일 오류가 발생한다
    • 식별자 검색 순서
      • 식별자가 선언된 위치를 검색하는 순서 // 이때 호출자보다 먼저 선언되야 함(윗줄에 존재해야함)
      • 전역 함수읜 경우
        1. 현재 블록 범위
        2. 현재 블록 범위를 포함하고 있는 상위 블록 범위(Max는 함수 몸체)
        3. 가장 최근에 선언된 전역변수 나 함수
        4. using 선언된 네임스페이스 혹은 전역 네임스페이스 / 이때 두 곳에 동일한 식별자 존재 시 컴파일 요류
      • 클래스 메서드인 경우
        1. 현재 블록 범위
        2. 현재 블록 범위를 포함하고 있는 상위 블록 범위(Max는 함수 몸체)
        3. 클래스의 멤버
        4. 부모 클래스의 멤버
        5. 가장 최근에 선언된 전역 변수나 함수
        6. 호출자 코드가 속한 네임스페이스의 상위 네임스페이스
        7. using 선언된 네임스페이스 혹은 전역 네임스페이스 / 이때 두 곳에 동일한 식별자 존재 시 컴파일 요류

연습문제

1. 다음 두 함수 원형에서 잘못된 점은 무엇인지 답하세요

- int TestFunc(int nParam1 = 5, int nParam2, int nParam3 = 10) 

- int TestFunc(int nParam1 = 5, int nParam2) 

= 초깃값 설정은 오른쪽부터, 중간에 빼먹을 수 없음

2. 다음 두 함수를 호출하는 코드에서 문제가 발생하는 이유

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

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

 = 함수의 모호성이 발생하기 때문( TestFunc(10) 실행시 모호성 오류 발생 )

3. 함수를 다중정의 하는것보다 템플릿이 더 좋은 코드가 될 가능성이 높은 이유?

= 템플릿으로 함수를 작성하면 유지보수 및 관리가 쉬워진다(다중정의는 N개를 바꿔야함, 템플릿은 하나만 바꾸면 됨)

4. inline 함수와 매크로의 공통된 장점

= 대입한다( 메모리 사용량이 낮아진다 )

5. 네임스페이스 미리 선언하는 법

= using namespace

6. 다음 코드의 실행결과

#include <iostream>

using namespace std;

 

int nData = 200;

 

namespace Test {

    int nData = 100;

    void TestFunc(void) {

        cout << nData << endl; // 여기서의 nData가 가리키는 것은? 1은 없음, 2로 100

    }

}

 

int _tmain(int argc, _TCHAR* argv[]) {

    TEST::TestFunc(); // 연산자 찾기

 

    return 0;

}

 

 

= 100