All Development

C++) C와 C++ 의 차이점 Part 2

Todah 2024. 1. 5. 20:02
반응형

1. 디폴트 파라미터

 

Caller -> Callee : 매개변수(실인수 기술)

  • 함수 선인 시 매개변수의 초깃값을 기술하는 문법이다.
  • 호출자 코드에서 피호출 함수 매개변수의 실인수를 기술하지 않을 경우 자동으로 초깃값이 적용된다.
  • 피호출자 입장에서 매개변수 디폴트 값은 반드시 오른쪽부터 선언해야 한다. ( 함수의 매개변수, 지역변수는 메모리의 Stack 영역에 저장되는데, 이때 오른쪽부터 저장이 되기 때문이다. )
  • 호출자 입장에서는 왼쪽 매개변수를 시작으로 기술하며 디폴트 파라미터로 선언된 매개변수들을 생략한다.
#include <iostream>

int testFunc(int param = 10)
{
	return param;
}

int main()
{
	std::cout << testFunc() << std::endl;
	std::cout << testFunc(20) << std::endl;

	return 0;
}

 

 

 

2. 함수 다중 정의

  • 함수의 원형이 달라야한다.
  • Caller 입장에서는 혼란스러울 수 있다. 함수의 원형을 정확하게 알고 사용해야 한다.
  • 다중 정의는 영문 Overloading에 대한 한글 번역표기이다.
  • 함수의 이름은 같지만 매개변수 구성이 다른 것이 특징이다. (반환 형식, 호출 규칙은 다중 정의 대상이 아님)
  • 디폴트 매개변수와 조합 시 모호한 호출오류가 발생한다.
  • C#이나 Java의 Override 와 동일한 기능이다.
#include <iostream>

int add(int a, int b, int c)
{
	std::cout << "add(int, int, int): ";
	return a + b + c;
}

int add(int a, int b)
{
	std::cout << "add(int, int): ";
	return a + b;
}

double add(double a, double b)
{
	std::cout << "add(double, double): ";
	return a + b;
}

int main()
{
	std::cout << add(3, 4) << std::endl;
	std::cout << add(3, 4, 5) << std::endl;
	std::cout << add(3.3, 4.4) << std::endl;

	return 0;
}

 

 

 

3. 함수 템플릿

  • 함수 다중 정의를 대체 할 수 있는 문법이며 함수 템플릿 사용을 권장한다.
  • Template은 일종의 '공판화 틀' 역할을 수행한다.
  • 함수 템플릿은 함수를 생성해내기 위한 근거가 되는 코드가 된다. (코드를 생성하기 위한 코드)
  • 생산성을 극대화할 수 있는 문법이다.
  • C#의 Generic 과 유사하다.
#include <iostream>

template <typename T>
T add(T a, T b)
{
	return (a + b);
}

int main()
{
	std::cout << add(3, 4) << std::endl;
	std::cout << add(3.3, 4.4) << std::endl;

	return 0;
}

 

 

 

4. Namespace

  • C++ 가 지원하는 각종 요소들 (변수, 함수, 클래스 및 각종 선언 등)을 한 범주로 묶어주기 위한 문법으로 중첩 가능하다.
  • 식별자 이름 앞에 ::를 붙여서 표기한다.
  • C언어의 전역변수나 함수는 C++문법상 모두 Global Namespace에 속한다.

ex) "std :: cout" : Namespace - std 라는 Namespace에 속한 cout을 뜻한다.

  • Namespace - using : Namespace 내에 있는 전역변수들은 Global Namespace 에서 선언된 전역변수들과 충돌을 일으키지 않는다.
  • Namespace는 중첩선언이 가능하다.
#include <iostream>

namespace Test
{
	int data = 100;

	void testFunc()
	{
		std::cout << "Test::TestFunc()" << std::endl;
	}
}

int main()
{
	Test::testFunc();
	std::cout << Test::data << std::endl;

	return 0;
}

 

 

 

5. 식별자 검색 순서

- 전역함수

  1. 현재 블록 범위
  2. 상위 블록 (최대 함수 바디)
  3. 최근에 선언된 전역변수나 함수
  4. using 선언된 게임 네임 스페이스 혹은 전역 네임스페이스

 

- 클래스 메서드

  1. 현재 블록 범위
  2. 상위 블록 (최대 함수 바디)
  3. 클래스 멤버
  4. (상속 시) 부모 클래스 멤버
  5. 최근에 선언된 전역변수나 함수 및 호출자 코드가 속한 네임스페이스
  6. using 선언된 네임스페이스 혹은 전역 네임스페이스

 

 

6. Name mangling

  • C++ 식별자(namespace, class) 이름은 컴파일러에 의해 C언어처럼 유일한 이름으로 자동변경.( H/W 시점에서 프로시저는 항상 유일한 이름을 가져야하기 때문이다.)
  • 함수 다중 정의의 작동원리
  • 식별자의 실제 이름은 링크 오류를 발생시켜 확인 가능

 

etc) Name mangling을 사용하지 않는 경우 :  C/C++로 개발을 할때는 보통 Module 수준에서 병합을 할텐데, DLL라이브러리에서 f(x)를 exe 수준에서 call해서 사용하게 된다. 이때 call 하는 구간에서 testFunc라는 이름이 없는 경우를 발견하게 되는데. 이때 컴파일러가 testFunc라는 이름을 Name mangling하기 때문이다.

 

extern "C" void testFunc() 을 사용하면 Name mangling을 하지 않는다.

다만 함수 다중 정의는 불가능해 진다.

반응형

'All Development' 카테고리의 다른 글

C++) C++의 특징 Part 2  (0) 2024.01.09
C++) C++의 특징 Part 1  (1) 2024.01.08
C++) C와 C++ 의 차이점 Part 1  (2) 2024.01.04
Unity) Lerp 의 사용법  (0) 2023.10.28
Sparta_algorithm_course_05) velog  (1) 2022.07.29