2024. 1. 3. 09:51ㆍUnreal 강의
함수 포인트
https://luinbarr.tistory.com/23
15일차 (1/2)
함수 포인터 //이런 형식으로 사용된다. void (*변수명)() //초기화는 보통 이렇게 한다. void (*Function)() = nullptr; //변수명 없이 사용하면 함수 포인터의 자료형이다. void(*)() 함수 포인터는 특정될 수
luinbarr.tistory.com
어제 수업한 함수 포인터 내용을 이어서한다.
Virtual이 없는 클래스는 내부를 살펴보면 다음과 같이 안에 내용이 없으므로 부모와 자신이 연결되어 있는 것만 표기한다.
모든 포인터는 8바이트다.(극한의 예외를 제외하면)
자료형*이라면 앞에 그 어떤 긴 코드가 있어도 포인터다.
{
int Arr[10];
int* Ptr = Arr;
int* ArrPtr[10];
int const* const* const* Ptr2D;
}
위의 코드에서 Ptr, ArrPtr[10], Ptr2D 모두 8바이트이다. 포인터가 몇중이든 무슨 자료형이든 상관없다.
가상함수테이블
가상함수 테이블이란 함수 포인터의 배열의 첫번째 주소를 가리키는 함수 이중 포인터라고 할 수 있다. 생성자에서 가상함수 테이블의 값들을 채워준다.
보다싶이 부모생성자가 호출될때 가상함수 테이블에 FightUnit의 함수들이 들어있다.
그 후 자식 생성자가 완전히 호출되면 가상함수 테이블의 함수 포인터가 교체된다.
그래서 이제부터 Damage를 호출하면 Damage를 컴파일러가 NewPlayer.Damage() => NewPlayer.vfptr[0]() 이렇게 바꿔버린다.
Enum
사용자 정의 자료형으로 정수형 상수를 정의하는 자료형이다.
enum Job
{
// 자동으로 맨위부터 0으로 채우고 아래쪽은 명시하지 않은 부분은 자연스럽게 위쪽 EnumType + 1
Fighter = 0, // Job::Fighter = 0
Mage, // Job::Mage = 1
};
값을 명시할수도 있다.
typedef가 문법적으로 별로 아름답지 못하다고 생각해서 만들어진 using이라는 문법도 있다. typedef와 다를게 없는 문법으로 똑같이 사용할 수 있다.
enum은 손쉽게 int가 될 수 있다.
int FighterInt = Job::Fighter;
int MageInt = Job::Mage;
다음과 같은 코드가 가능하다. 그러나 형변환은 줄일수록 안전하다.
그래서 enum class라는 문법이 있다.
enum class DamageType
{
PDamage,
MDamage,
};
DamageType Type = DamageType::MDamage;
이런 식으로 사용한다. enum class를 사용하게되면 int에 넣으려고 할때 오류가 뜬다.
만약 enum class를 사용하는데 강제로 형변환을 하고 싶다면 방법이 있긴하다.
int Value3 = Type;
int Value0 = static_cast<int>(Type);
int Value1 = (int)Type;
그러나 이렇게 쓸 경우는 없다고 봐도 된다.
namespace
이름이 겹치는 클래스가 있는 것을 막기 위해 사용한다.
앞에 접두사를 붙이는 기능으로 FullName에 접두사를 붙이고 영역을 구분시킨다.
namespace안에 또 namespace를 만들수도 있다.
보통 이름을 붙여주기보다는 작업영역을 나눠놓고 싶을 때 사용하는게 좋다.
만약 using namespace 네임스페이스명 이런식으로 include처럼 앞에 명시할 경우 네임스페이스명을 사용하지 않고도 그 안의 기능들을 사용할 수 있으나 이렇게 사용할거면 그냥 namespace안에 안넣어두면 된다.
cout등을 사용할 때 앞에 붙이는 std:: 또한 c++언어 차원에서 스탠다드로 지원하는 기능이라는 뜻인 namespace이다.
동적 할당
게임의 모든 데이터를 한번에 메모리에 올릴 수는 없다. 올릴 수 있더라도 비효율적이다. 그렇기 때문에 필요한 것만을 올리기 위해 사용하는 것이 동적 할당이다.
지금까지 해왔던 메모리 바인딩들은 정적 바인딩이다. 정적 바인딩은 플레이 도중에 절대로 메모리의 크기를 유동적으로 처리할 수 없다.
정적 바인딩은 이미 정해진 크기대로밖에 만들 수 없고 수정이 불가능한 메모리 사용 방식이다.
포인터 클래스를 생성할 때 new 연산자를 앞에 붙이면 조건에 맞춰서 생성할 수 있다 이게 동적 바인딩이다.
Zone* NewZone = nullptr;
if (플레이어가 들어왔다면)
{
NewZone = new Zone();
}
//배열로 할당하는 방법
Monster* NewMonster = new Monster[MonsterCount];
전역변수 => 데이터 영역
지역변수 => 스택 영역
상수 => 코드 영역
동적 할당은 힙이라고 하는 메모리를 사용하는 문법이고 메모리의 크기는 운영체제가 할당해주지만 거의 램크기만큼 할당할 수 있다.
삭제하는 방법은 delete 포인터 변수명을 하면된다.
delete NewZone;
//배열 할당을 삭제하는 방법
delete[] NewMonsterArr;
leck
leck이라는 것은 동적 할당으로 new를 생성했는데 delete를 하지않아 메모리를 계속 할당하고 있는 것이다. 만약 릭이 남아있는 것이 발견된다면 모든 코딩을 정지하고 릭부터 해결해야한다. 릭이 남아있다는 것은 심각한 상황이다.
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
leck을 검사해주는 코드로 동적 할당을 사용하게 된 이후부터는 항상 main 가장 위(프로그램의 시작 부분)에 두어야 하는 코드이다. 시작부분에 놓지 않으면 릭을 못잡는 경우가 생길수도 있다.
'Unreal 강의' 카테고리의 다른 글
18일차 (1/5) (0) | 2024.01.05 |
---|---|
17일차 (1/4) (0) | 2024.01.04 |
15일차 (1/2) (0) | 2024.01.02 |
14일차 (12/29) (0) | 2023.12.29 |
13일차 (12/28) (0) | 2023.12.28 |