https://ansohxxn.github.io/cpp/chapter13-1/
일단 모두의 코드 말고 이분의 블로그를 정리 하겠다.
int getMax(int x, int y)
{
return (x > y) ? x : y;
}
double getMax(double x, double y)
{
return (x > y) ? x : y;
}
float getMax(float x, float y)
{
return (x > y) ? x : y;
}
템플릿 을 쓰기전에는
템플릿은 컴파일 타임에 결정되는 것만 쓸 수있다? (프로세싱타임 아니야?)
template <typename T>
T getMax(T x, T y)
{
return (x > y) ? x : y;
}
int main()
{
std::cout << getMax(1, 2) << std::endl;
// T가 int로 구체화
// int getMax(int x, int y)
std::cout << getMax(3.14, 1.1592) << std::endl;
// T 가 double로 구체화
// double getMax(double x, double y)
std::cout << getMax(1.0f, 3.4f) << std::endl;
// T 가 float 로 구체화
std::cout << getMax(Cents(5), Cents(9)) << std::endl;
// T가 Cents객체로 구체화
// Cents getMax(Cents x, Cents y)
}
<<
>
y)?X:y일반화
#include <iostream>
template <typename T>
class MyArray
{
private:
int m_len;
T *m_data;
public:
MyArray(int len)
{
m_data = new T[len];
m_len = len;
}
~MyArray()
{
reset();
}
void reset()
{
delete[] m_data;
m_data = nullptr;
m_len = 0;
}
T &operator[](int index)
{
assert (index >= 0 && index < m_len);
return m_data[index];
}
int getLen()
{
return m_len;
}
void print()
{
for (int i=0; i<m_len; i++)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
};
클래스 템플릿은 그 자체로 클래스는 아니다. 클래스 틀일 뿐
구체화
int main()
{
MyArray<char> my_array(10);
for (int i =0; i< my_array.getLen(); ++i)
my_array[i] = i + 65;
my_array.print();
return 0;
}
객체이름[]
으로 바로 동적 배열 멤버의 원소에 접근할 수 있다.클래스 템플릿은 헤더파일, cpp 로 분리하지 않는게 좋다.
분리할 경우 -> 링킹 에러 발생
print() 멤버함수의 선언과 정의를 나눠보자
MyArray.h
#include <iostream>
template <typename T>
class MyArray
{
... // 다른 부분들은 위와 동일
void print(); // ⭐ 선언만
};
#include "MyArray.h"
template <typename T>
void MyArray<T>::print()
{
for (int i = 0; i < m_length; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
#include "MyArray.h"
int main()
{
MyArray<char> my_array(10);
for (int i = 0; i < my_array.getLength();++i)
my_array[i] = i + 65;
my_array.print(); // 💥 링킹 에러 발생
return 0;
}
컴파일엔 문제가 없으나 링킹 에러 발생 !
링킹 에러이유
MyArray.cpp 파일을 컴파일 할 때, 어떤 자료형으로 클래스를 구체화 해야하는지 몰라서
print()함수의 바디 부분이 메모리에 정의가 되지 않기 때문이다.
컴파일
cpp 파일들만 컴파일 한다.
문법체크 + static 한 영역들 메모리 할당 일을 수행한다.
#include "MyArray.h"
#include "MyArray.cpp"
그러나 이 방법은 비추. .cpp파일 까지 포함하는 일은 프로그램이 커질시 복잡해짐.
#include "MyArray.h"
template <typename T>
void MyArray<T>::print()
{
for (int i = 0; i < m_length; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
template void MyArray<char>::print();
template void MyArray<double>::print();
#include "MyArray.h"
template <typename T>
void MyArray<T>::print()
{
for (int i = 0; i < m_length; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
template class MyArray<char>;
template class MyArray<double>;
클래스 템플릿 헤더 파일 내에서 전부 구현 하는것.
클래스 템플릿은 선언부, 구현부 각각 헤더파일, cpp파일로 나누지 말고
그냥 헤더파일 내에서 다 구현 ! 선언 + 구현 까직
MyArray.h
#include <iostream>
template <typename T>
class MyArray
{
...
void print()
{
for (int i = 0; i < m_length; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
};
#include <iostream>
template <typename T, unsigned int T_SIZE> // ⭐
class MyArray
{
private:
// int m_length; ⭐
T * m_data;
public:
MyArray()
{
m_data = new T[T_SIZE]; // ⭐
}
~MyArray()
{
reset();
}
void reset()
{
delete [] m_data;
m_data = nullptr;
// m_length = 0;
}
T & operator [] (int index) // ⭐
{
assert (index >= 0 && index < T_SIZE);
return m_data[index];
}
int getLength()
{
return T_SIZE; // ⭐
}
void print()
{
for (int i = 0; i < T_SIZE; ++i) // ⭐
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
};
#include "MyArray.h"
int main()
{
MyArray<double, 100> my_array;
for (int i = 0; i < my_array.getLength();++i)
my_array[i] = i + 65;
my_array.print();
return 0;
}
MyArray<double, 100> my_array;
int a = 100;
MyArray<double, a>my_array; // Error
const int a = 100;
MyArray<double, a>my_array; // Error