함수 템플릿(template)

Yama·2023년 12월 26일
0

어소트락 수업

목록 보기
25/55

지금까지 만든 클래스 가변 배열

  • int 자료형만 동적 배열한다.
  • 힙 메모리에 동적할당을 할떄. 내가 원하는 단위로 점프 뛸떄도 그 단위로 접근할떄도 int로 접근했다.
  • 만약 이걸 다른 자료형들로 동적 배열을 만들고 싶다면 노가다를 해서 직접 다 만들었어야한다.
    • 내가 만든 구조체의 클래스를 개발하는 과정에서 설계하는 자기만의 자료형인데 그걸 대응하는 동적배열을 만들어 줄 수 없다.
  • 그래서 이걸 우리가 짜는게 아니라 컴파일러한테 구분해서 시킬 수 있다.
    • 함수 템플릿

함수 템플릿

int Add(int a, int b) 		// 3
{
	return a + b;
}

float Add(float a, float b) // 4
{
	return a + b;
}


int main()
{
	Add(10, 10);	// 1
    
    Add(4.1f, 2.2f); // 2

	return 0;
}
  • 이건 함수 오버로딩을 통해서 무슨 인자를 전달하는지에 따라 1번은 3번에 2번은 4번에 들어간다.
  • 근데 이걸 어떤 자료형이 오던 대응되게 할것이다. -> Add함수 템플릿으로 바꾸기
template<typename T>
T Add(T a, T b)
{
	return a + b;
}

int main()
{
	int value = Add<int>(10, 10);	 	// 1
    
	value = Add<float>(1.2f, 3.5f); 	// 2

	return 0;
}
  • 아직 함수가 아니라 함수가 될 가능성이 있는놈
  • 컴파일러는 함수라 보지 않고 템플릿을 호출할려고 하면 <int'>가 설계도면상의 T로 들어가서 함수로 된다.
  • Add<int'>를 호출했기 때문에 템플릿이 함수로 변해서 최종코드에서는 함수가 될것이다.
  • 클래스 템플릿도 int 버전1번과 float의 2번은 완전 다른 클래스다.

함수 템플릿 (2)

#include<vector>
using std::vector;

int main()
{
	vector<int> vecInt;			// 1
	vector<float> vecFloat; 	// 2
}
  • 1번과 2번은 형태는 비슷하겠지만 완전 다른 클래스다.
  • 표준 라이브러리 동적배열 vector는 클래스 템플릿이다.
	// 메인 함수 전처리기 등등 생략.
	int value = Add(10, 10);	// 1
	value = Add(1.2f, 3.5f);	// 2
  • 원칙적으로는 함수 템플릿에 타입을 지정해줘야 한다.
  • but 컴파일러가 입력 인자의 타입을 분석해서 자동으로 특정 타입을 정해서 함수 템플릿을 작성한다.
  • 따라서 겉으로 보기에 마치 일반 전역 함수를 호출하는 것처럼 보일 수 있으나
  • 엄연히 함수 템플릿을 사용 한 것.
    • 템플릿에서는 <int'>,<float'>를 생략해도 컴파일러는 ()안에 인자를 보고 자동적으로 만들어준다.
  • 2번처럼 함수 템플릿에 컴파일러가 float버전을 호출한것이겠지하고 자동적으로 해준것. T가 float으로 변해서 일반 함수를 호출하듯이 인자를 잘 골라주면 해당함수를 호출하듯이 사용할 수 있다.

namespace와 ::(스코프 연산자)

  • 프로그래밍을 하다보면 변수명이 겹치는 경우가 존재한다.
    • 내가 제공해준 코드의 함수 이름과 다른 사람이 쓰는 함수명이 겹칠수 있다리.

using namespace MY_SPACE;	// 10

namespace MY_SPACE 
{
	void TestFunc() 		// 5
	{

	}

	int g_Global = 0;		// 6
}

void TestFunc()				// 7
{

}

int g_Global;				// 8 
int g_Globa2 = 0;

namespace MY_SPACE			// 9
{
	int g_Globa2 = 0;
}

int main()
{
	MY_SPACE::TestFunc(); 	// 1

	TestFunc();				// 2
    
    g_Global = 100;			// 3
	MY_SPACE::g_Global = 10;// 4

}
  • namespace 사용, 범위 지정 연산자를 이용해서 원하는 namespace 안에 구현된 기능에 접근 할 수 있다.
  • 1번은 호출하면 5번으로 들어간다 2번은 호출하면 7번으로 간다 3번은 호출하면 8번으로 인식할것이고 4번은 6번으로 인식될것이다.
  • 9번처럼 namespace를 띄엄띄엄 선언해서 MY_SPACE에 넣어 줄수 있다.
  • 변수명, 함수명, 클래스명, 매크로이름 등등, 모든 부분에서 이름적으로 겹치는 일이 없도록 각자 자기만의 namespace 안에 기능들을 구현
  • 10번을 적어버리면 오류 발생한다.
    • 이유는 아래에서.
#include <iostream>
#incldue <vector>

using namespace std; // 1

int main()
{
	std::vector<int> vecInt;
	std::vector<float> vecFloat;
}
  • using namespace 네임스페이스이름;
    • 해당 네임스페이스를 무효화 처리한다.
    • namespace 안에 모든것을 해제시키기 때문에, 원래 목적을 상실
  • using 네임스페이스이름::기능;
    • 해당 네임스페이스 안에 특정 기능만 namespace 범위 해제.
  • 1번처럼 namespace std; std안에 구현되어있는 모든걸 무효화시킨다.
using std::vector;
  • 표준 라이브러리안에 모든게 std안에 다 들어가 있다. 그렇기 때문에 모든 것을 using namespace std 사용하여 무효화하는게 아니라, 필요할떄 특정 기능 하나씩만 열자.

스코프 연산자

int data = 10;

int main()
{
	int data = 0;
    data = 10; 			// 1
    ::data = 10;		// 2

}
  • 1번처럼 하면 스택메모리의 data를 가리키고
  • 2번처럼하면 인지범위의 바깥쪽으로 돌려서 전역변수를 지칭하게 한다.
  • 함수 지역안에서 호출할 변수의 우선순위를 전역변수로 바꾸고 싶은 경우.
void Realloc()			// 4
{

}


void CArr::push_back(int _Data)
{
	if (m_MaxCount <= m_CurCount)
	{
		Realloc();		// 1
		::Realloc();	// 2

	}
}
void CArr::Realloc()	// 3
{
	
}
  • 1번케이스는 3번을 지목한다. 우선순위때문에
  • 2번케이스는 4번을 지목한다.
  • 맴버 함수내에서 호출할 함수의 우선순위를 전역함수로 바꾸고 싶은 경우.

강의 코드

main.cpp

#include <iostream>

#include <vector>
#include <string>
#include <list>
#include <set>
#include <map>
#include <unordered_map>
#include <queue>
#include <algorithm>
//using namespace std;
using std::vector;

std::string;
std::wstring;
std::list<int>;


namespace MY_SPACE
{
	void TestFunc()
	{

	}

	int g_Global = 0;
}

int g_Global = 0;
int g_Global2 = 0;

void TestFunc()
{

}


namespace MY_SPACE
{
	int g_Global2 = 0;
}

//using namespace MY_SPACE;

#include "CArr.h"

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


int data = 10;

int main()
{
	MY_SPACE::TestFunc();
	TestFunc();

	MY_SPACE::g_Global = 100;
	g_Global = 100;

	int data = 0;
	data = 10;

	::data = 10;

	int value = Add(10, 10);
	value = Add(1.2f, 3.5f);

	Add<float>(1.2f, 3.5f);
	Add<float>(1.2f, 3.5f);

	std::vector<int>	vecInt;
	std::vector<float>	vecFloat;

	return 0;
}

1차 23.12.26
2차 23.12.27
3차 23.12.28
4차 23.12.29
5차 24.01.02
6차 24.01.03

0개의 댓글