함수 포인터 #1
int* pointer = &a
int
: 데이터 타입pointer
: 변수 이름
int Add(int a, int b)
{
return a + b;
}
int main()
{
typedef int(FUNC_TYPE)(int a, int b);
using FUNC_TYPE = int(int a, int b); // modern C++
FUNC_TYPE* fn = ADD;
int result = fn(1, 2);
int result2 = (*fn)(1, 2);
}
FUNC_TYPE* fn = ADD()
FUNC_TYPE
: 데이터 타입fn
: 변수 이름Add
: 주소를 저장할 대상 함수
함수의 이름은 함수의 시작 주소를 가짐(배열과 유사)
함수 포인터에는 접근 연산자 *
를 붙여도 함수 주소를 가리킴
class Item
{
public:
Item() : _itemid(0), _rarity(0), _ownerid(0) {}
public:
int _itemid;
int _rarity;
int _ownerid;
}
Item* FindItem(Item items[], int itemCount, bool(*selector)(Item* item))
{
for (int i = 0; i < itemCount; i++)
{
Item* item = &items[i];
if (selector(item))
return item;
}
return nullptr;
}
bool IsRareItem(Item* item)
{
return item->_rerity >= 2;
}
int main()
{
Item item[10];
items[3]._rarity - 2;
Item* rareItem = FIndItem(items, 10, isRareItem);
}
함수 포인터 #2
typedef
는 선언 문법의 앞에 붙이는 형식으로 사용
보통은 int (*PFUNC)(int, int);
와 같은 형식으로 함수 포인터 시그니처를 만들어 사용함
class Knight
{
public:
int GetHP(int, int)
{
...
}
public:
int _hp = 100;
}
typedef int(Knight::*PMEMFUNC)(int, int);
int main()
{
Knight k1;
Knight* k2 = new KNight();
PMEMFUNC mfn;
mfn = &Knight::GetHP;
(k1.*mfn)(1, 2);
(k2->*mfn)(1, 2);
delete k2;
return 0;
}
멤버 함수는 특정 객체를 기반으로 호출됨
함수 포인터에 함수의 주소를 대입할시 &
는 생략이 가능하나, 붙이는 것이 권장됨
특히 멤버 함수를 함수 포인터에 대입할 때는 반드시 &
를 붙어야함
멤버 함수를 함수 포인터로 사용시 객체가 필요하며, (k1.*mfn)(1, 2);
와 같은 형식으로 사용하여 해당 객체의 멤버가 아닌 함수 포인터라는 것을 지정해야함
함수 객체
함수 포인터 단점
- 함수 시그니처가 맞지 않으면 사용할 수 없음
- 상태를 가질 수 없음
함수 객체(Functor) : 함수처럼 동작하는 객체
class Functor
{
public:
void operator()()
{
cout << "Functor Test" << endl;
cout << _value << endl;
}
boll operator()(int num)
{
cout << "Functor Test" << endl;
_value += num;
cout << _value << endl;
return true;
}
private:
int _value = 0;
}
int main()
{
Functor funcotr;
functor();
bool ret = functor(3);
return 0;
}
함수 객체를 생성하는 시점과 실행하는 시점을 분리할 수 있음
class MoveTask
{
public:
void operator()()
{
cout << "해당 좌표로 플레이어 이동" << endl;
}
public:
int _playerid;
int _posX;
int _posY;
}
int main()
{
MoveTask task;
task._plyaerid = 100;
task._posX = 5;
task._posY = 0;
// 이동 요청을 받아서 함수 객체에 저장
// 요청을 곧바로 실행하지 않고, 얼마든지 나중에 task를 실행할 수 있음
task();
}
템플릿 기초 #1
template <typename T>
void Print(T a)
{
cout << a << endl;
}
int main()
{
print(50);
print(50.0);
print("Hello World");
print<int>(50.0f);
return 0;
}
템플릿 : 함수나 클래스를 찍어내는 틀
- 함수 템플릿과 클래스 템플릿이 존재
template <typename T>
또는template <class T1, class T2>
의 형식으로 사용
class Knight
{
public:
...
public:
int _hp = 100;
};
template <typename T>
void Print(T a)
{
cout << a << endl;
}
template<<>
void Print(Knight a)
{
cout << "Knight!!!" << endl;
cout << a._hp << endl;
}
ostream& operator<<(ostream& os, const Knights& k)
{
os << k._hol
return os;
}
int main()
{
Knight k1;
Print(k1);
}
Knight
클래스형으로 Print
함수를 사용하고 싶은 경우, Print
함수에서 사용하는 <<
연산자에 대해 Knight
형의 오버로딩이 필요함
또는 템플릿 특수화를 통해 Print
템플릿 함수를 Knight
에 대해서만 재정의할 수 있음
템플릿 기초 #2
template<typename T, iny SIZE>
class RandomBox
{
public:
T GetRandomData()
{
int idx = rand() % 10;
return _data[idx];
}
public:
T_data[SIZE];
}
template<int SIZE>
class RandomBox<double, SIZE>
{
public:
T GetRandomData()
{
cout << "RandomBox Double" << endl;
int idx = rand() % 10;
return _data[idx];
}
public:
T_data[SIZE];
}
int main()
{
srand(static_cast<unsigned int>time(nullptr));
RandomBox<int, 10> rb1;
for (int i = 0; i < 10; i++)
rb1._data[i] = i;
int value1 = rb1.GetRandomData();
cout << value1 << endl;
RandoBox<double, 20> rb2;
for (int i = 0; i < 20; i++)
rb2._data[i] = i + 0.5f;
int value2 = rb2.GetRandomData();
cout << value2 << endl;
}
클래스 템플릿도 함수 템플릿과 거의 비슷하게 사용
서로 다른 인수를 사용하면 서로 다른 템플릿 클래스가 생성되며, 각각 별개의 클래스로 취급됨
템플릿 특수화도 사용 가능
콜백 함수
콜백(Callback) : 어떤 상황 발생시 특정 기능을 호출
class Item
{
public:
public:
int _itemid = 0;
int _rarity - 0
int _owenerid = 0;
};
class FindByOwnerid
{
public:
bool operator()(const Item*)
return (item->_ownerid == _ownerid);
public:
int _owenerid;
};
class FindByRarity
{
public:
bool operator()(const Item*)
return (item->_rarity == _rarity);
public:
int _rarity;
};
template <typename T>
Item* Finditem(Item items[], int itemCount, T selector)
{
for (int i = 0; i < itemCount; i++)
{
Item* item = &items[i];
if (selector(item))
return item;
}
return nullptr;
}
int main()
{
Item items[10];
FindByOwnerid functor1;
functor1._ownerid = 100;
FindByRariry functor2;
functor2._rarity = 1;
Item* item1 = Finditem(items, 10, functor1);
Item* item2 = Finditem(items, 10, functor2);
return 0;
}
'개인공부 > Rookiss C++ 프로그래밍 입문' 카테고리의 다른 글
Chapter 12 - Modern C++ (0) | 2023.03.29 |
---|---|
Chapter 11 - STL (0) | 2023.03.29 |
Chapter 9 - 디버깅 (0) | 2023.03.29 |
Chatper 8 - 실습 (0) | 2023.03.29 |
Chapter 7 - 동적 할당 (0) | 2023.03.29 |
댓글