함수 객체 함수 객체(Functor), 함수처럼 동작하는 객체 함수 포인터의 단점이 있었다. 그 시그니처와 동일하지 않은 함수는 사용할 수 없다는 점이다. 또, 상태를 가질 수 없다는 점이 단점이다. 클래스에는 데이터와 함수를 동시에 가질 수 있다. hp가 100 이라면 100이라는 상태를 가지고 있는 것이다. 함수처럼 동작 하는 객체가 함수 객체이다. () 연산자 오버로딩이 필요하다. #include using namespace std; class Func { public: void operator()() { cout
분류 전체보기
STL의 공부하기 위헤서 필수적으로 알고 있어야한다. 함수 포인터 포인터는 주소를 담는 바구니 이다. int* pointer = &a; 포인터라는 것을 알려주기 위해 * 를 사용하고 변수 이름은 pointer 이다. 데이터 타입은 int인 것이다. 지금까지 우리가 사용한 데이터 타입은 기본 타입 들과 우리가 제공한 class 나 struct 등을 사용했지만 이것 이외에도 바로 함수 타입이다 #include using namespace std; int Add(int a, int b) { return a + b; } int main() { // 함수 포인터 // int 2개를 받아 int 하나를 반환하는 시그니처 함수 typedef int(FUNC_TYPE)(int, int); // 1) 포인터* // 2)..
이번 포스팅은 지금까지 배운 내용으로 TextRPG를 만들다가 느낀 C++에 관한 내용을 적어보려고 한다. 전방 선언 이전 포스팅에서 글로만 다뤘던 내용인데, 이 부분이 익숙하지 않았다. 그래서 Player 클래스와 Item 클래스가 각기 다른 Player.h, Item.h 파일에 이렇게 있다고 해보자. Item.h #pragma once #include "Player.h" class Item { public : void UseItem(const Player* player); }; Player.h #pragma once #include "Item.h" class Player { public: Item* _item; }; 위 코드는 플레이어가 아이템을 가지고 있고, 그 아이템은 능력을 사용하기 위해서 사용..
전방 선언 전방 선언이 왜 필요할까? 우리가 어떤 클래스를 스텍이나 힙 등에 메모리에 할당하기 위해서는 그 클래스의 size를 알아야 메모리에 할당이 가능하다. 그런데 그 클래스안에 다른 클래스를 멤버 변수로 들고 있다고 해보자. 그러면 그 클래스의 size를 알 수 있을까??? 알수 없다. 예를 들어 Player 파일과 Monster 파일 그리고 Main 파일이 있고 Player 클래스 안에 Monster 라는 멤버 변수를 가지고 있다고 해보자. 그리고 우리가 어떤 함수에서 Player * p = new Player; 를 통해 동적할당을 하면 에러가 날 것이다. 그 이유는 Player의 정확한 size를 모르기 때문이다. 왜 모를까? Monster라는 클래스의 size를 건네 받지 못했기 때문이다. 이..
얕은 복사 면접에도 자주 등장하는 단골 질문이다. 오늘 사용할 class를 만들어보자. #include using namespace std; class Knight { public: public: int _hp = 100; }; int main() { // 그대로 복사하고 싶은 경우 Knight knight; knight._hp = 200; // 여러 방법 존재 Knight knight2 = knight;// 복사 생성자 Knight knight3; knight3 = knight;// 복사 대입 연산자 return 0; } 우리가 Knight 클래스에 아무런 코딩을 하지않았는데 빌드가 잘 되는 것을 볼 수 있다. 복사 생성자와 복사 대입 연산자를 직접 만들지 않으면 컴파일러가 암시적으로 만들어준다. 그렇..
타입 변환 (포인터, 연관 없음) #include using namespace std; class Knight { public: int _hp = 10; }; class Item { public: Item() { cout
malloc을 사용할 때 void*을 반환하고, 이를 우리가 타입 변환을 통해 사용했었다. 타입 변환 유형(비트열 재구성 여부) [1] 값 타입 변환 의미를 유지하기 위해서, 원본 객체와 다른 비트열을 재구성하는 것 int a = 123456789;// 2의보수 float b =(float)a;// 부동소수점(지수 + 유효숫자) 둘의 메모리를 확인해보면 둘이 아예 다르다는 것을 확인 할 수 있다. int를 float를 변환한것을 보면 데이터의 값은 얼추 비슷하지만(정수를 실수로 바꾸다보면 누락될 수 있음) 둘의 비트 저장 방식이 다르다 보니 비트열을 아예 바꿔 재구성한 것이다. [2] 참조 타입 변환 비트열을 재구성하지 않고, 비트를 분석하는 관점만 바꾸는 것이다. int a = 123456789;// ..
메모리 구조 우리가 C++을 다루면서 메모리 영역에 대해 많이 다뤄봤다. 특히 데이터 영역과 스택 영역에 대해 정말 많이 그리고 중요하게 다뤘다. 실행할 코드가 저장되는 영역이 코드 영역이고 전역(global)/정적(static) 변수가 데이터 영역에 할당된다. 또 지역변수/ 매개변수는 스택 영역에 할당된다. 그렇다면 마지막 힙 영역은 누가 차지 하느냐 바로 동적 할당한 데이터가 힙 영역을 차지한다. 예를 들어보자. MMOPRG는 동접자가 1명~5만명 정도 되고, 몬스터는 1마리~500만 마리 있을 것이다. 지금까지 배운 내용으로 이걸 구현하기 위해선 몬스터 배열을 500만을 잡아야한다. Moster monster[500 * 10000];을 할것이다. 다만 이렇게하면 스택 오버플로우가 날것이다. 즉 메모..
연산자 오버로딩 만약 플레이어의 위치를 저장하는 Position class가 있다고 해보자. #include using namespace std; class Position { public: public: int _x; int _y; }; int main() { Position pos1; pos1._x = 1; pos1._y = 1; Position pos2; pos2._x = 2; pos2._y = 2; Position pos3 = pos1 + pos2; return 0; } 그래서 플레이어가 pos1에 있다가 pos2 만큼 이동해서 pos3의 위치로 이동하고 싶은데 지금 같은 상황에선 에러가 나는 모습을 볼 수 있다. 이를 해결하기 위해 연산자를 마음대로 커스터 마이징 하는 연산자 오버로딩을 할것이다..
은닉성 지난 포스팅에서 객체 지향의 3대장중 상속성에 대해 알아 봤다. 이번 포스팅에서는 은닉성 다형성 등에 대해 알아보자. 은닉성이란 캡슐화라는 단어로 많이 쓴다. Data Hiding으로 몰라도 되는 것은 깔끔하게 숨기겠다. 라는 의미이다 왜 숨길까?? 정말 위험하고 건드리면 안되는 경우와 다른 경로로 접근하길 원하는 경우에 사용한다. 자동차를 설계한다고 해보자. 핸들 페달 엔진 문 각종 전기선 등등 개발자 입장에선 위를 고려해야한다. 하지만 일반 구매자 입장에서 사용하는 것은 핸들 페달 문 이정도이다. 나머지 엔진이나 각종 전기선은 오히려 건드리면 큰일이 나곤한다. #include using namespace std; class Car { public: void MoveHandle() {} void..