Unreal 강의

11일차 (12/26)

루인엘다 2023. 12. 26. 10:39
메모리

비어있는 클래스의 메모리 사이즈는 1이다. 논리적으로 생각하면 0바이트가 맞지만 0바이트를 허용하면 많은 문법이 무너지기 때문에 1바이트이다. 0바이트일 경우 포인터나 배열 문법들이 망가진다.

 

함수는 비어있어도 0바이트이다. 함수는 클래스의 크기에 영향을 주지 않는다.

//비어있어서 1바이트
class A
{
};

//함수는 0바이트라 비어있는 클래스는 1바이트
class B
{
public:
    void Fuction()
    {
    }
};

//1바이트 변수가 있어서 1바이트
class C
{
public:
    bool Test0;
};

//8
class D
{
public:
    bool Test0; //4
    int Test1; //4
};

//12
class E
{
public:
    bool Test0; //1
    // Temp; 1
    // Temp; 1
    // Temp; 1
    int Test1; //4
    bool Test2; //4
};

//8
class F
{
public:
    bool Test0; //1
    bool Test1; //1
    // Temp; 1
    // Temp; 1
    int Test2; //4
};

//16
class G
{
public:
    bool Test0; //1
    bool Test1; //1
    // Temp; 1
    // Temp; 1
    // Temp; 1
    // Temp; 1
    // Temp; 1
    // Temp; 1
    __int64 Test2; //8
};

이렇게 가상 메모리를 사용하여 정렬하는 것을 바이트 패딩이라한다.

바이트 패딩 규칙
  • 전 멤버변수 중에 가장 큰 바이트 크기를 가진 기본자료형을 찾는다. (순서는 중요하지 않다.)
  • 어떤 바이트의 변수가 나오던지 찾은 가장 큰 바이트로 할당한다.
  • 그 안에서 다시 가장 큰 자료형으로 정렬한다.
  • 그 다음 바이트가 4혹은 8바이트안에 함께 들어갈 수 있는 변수라면 그 뒤에 채운다. (1바이트 자료형을 제외하고 홀수가 되면 안된다.)

바이트 패딩이 되는 이유는 하드웨어가 짝수로만 보낼 수 있기 때문이다.


this

클래스를 포인터로 사용할때는 .이 아니라 ->를 사용한다. 그리고 if (nullptr == 포인터)를 방어코드로 사용한다.

멤버함수는 기본적으로 __thiscall형태의 함수가 된다.

__thiscall은 자신을 호출한 객체의 포인터를 첫번째 인자로 받는다. 

class Player 
{
private:
    int Att = 10;
    int Hp = 100;

public:
    void __thiscall Damage(Player* const _this, int _Damage)
    {
        _this->Hp = 20;
    }
};

this는 포인터 뒤 const이기 때문에 자기자신의 주소값을 바꿀 수 없다.

 

같은 클래스를 사용하는 객체들은 서로의 private 변수를 사용해도 자기 자신인지 확인할 방법이 없어서 사용이 된다.


선언

함수명과 인자만 적어두는 것이다. 이런 함수가 있을거니 믿고 호출해도 된다는 의미로 사용한다. 많이 있어도 상관없다. 

나중에 구현이 있을것이고 호출해 놓으면 구현과 연결될거라고 컴파일러에게 알려준다.

 

구현

선언한 내용의 구현을 만나면 링커가 구현부를 선언부와 연결해준다. 만약 선언만이 있고 그 선언과 일치하는 구현이 없으면 에러가 난다.

 

클래스 함수의 선언과 구현의 분리는 클래스 바깥쪽에서 이루어진다. 그때는 FullName으로 사용해야한다.

보통 클래스 이름 ::(범위 확인 연산자) 함수 이름 으로 선언한다.

 

함수의 구현을 위쪽에 하는 것이 이득이 없기 때문에 선언은 위쪽에 전부 남기고 구현은 아래쪽에 몰아넣는 형태가 된다.

 

헤더 cpp 나누기

클래스 파일을 생성한 후 생성된 헤더 파일(. h)에 클래스의 선언만 남긴다.

헤더에는 앞에 #pragma once를 꼭 넣어야한다. 헤더가 중복되는 것을 방지해주는 전처리기이다. 이게 있어야 같은 헤더를 여러개 넣어도 에러가 나지않는다.

 

.cpp 파일에는 위와 같이 클래스::함수명으로 이루어진 함수들만 남긴다.

 

선언과 수현을 분리하면 inline이 되지 않는다.

굉장히 간단한 함수들은 선언과 구현을 분리하지 않는다. 대표적으로 get, set, 특히 get 함수는 하지 않는 편이다.

 

위에 다른 내가 만든 클래스를 절대로 추가하지않는 클래스의 경우 헤더만 생성해도 된다.

 


에러
  • 에러는 위에서부터 아래로 읽어야 한다. 위에서 난 에러 때문에 아래있는 에러가 났을수도 있기 때문이다.
  • 에러는 출력창에서 확인한다. 만약 보이지 않는다면 보기 - 출력에서 확인 가능하다.
  • warning => 이게 실행을 못할 정도는 아닌데 문제가 있다.
  • 식별자를 찾을 수 없습니다. => 선언조차 존재하지 않는다.
  • 함수에서 참조되는 확인할 수 없는 외부 기호 => 함수나 변수가 선언만 있고 구현이 없다.

프로그래밍 시에 주의할 점
  • 하다가 안됐으면 취소하고 다 지운다.
  • 완벽한거같은데 안되면 결과물 다 삭제하고 컴퓨터 재부팅을 한다.
  • 일부러 틀린 값을 넣어서 에러처리가 제대로 됐는지 확인한다.
  • 커밋은 자주 해야한다.
  • 헤더를 만들 경우 확실히 include해주었는지 확인해야한다.
  • 대소문자 확실히 확인해야한다. 확실하게 하려면 한쪽을 복붙해서 붙여본다.

단축키
  • 프로젝트or필터 선택 후 Ctrl + Shift + a => 새 파일 생성