공부/Unity

24.04.19

월러비 2024. 4. 22. 18:20

형식

  • C++에는 값형식, 참조형식이 없다
  • C++의 클래스와 구조체의 차이는 (녹음)
  • C++은 구조체 상속이 가능하다. (C#은 구조체 상속이 불가능하다)
    • 데이터 위주 : 구조체를 사용한다.
    • 기능 위주 : 클래스를 사용한다.
  • C++은 구조체를 생성할때 중괄호 끝에 세미콜론 (;)을 붙여야한다.
struct A
{
	int b;
	int c;
};
A ob; //ob에는 b 공간과 c 공간이 있다.
ob.b = 10; //ㅠrhdrksdp 10dl emfdjrkTek.
A* obp = new A(); //obp는 32비크?(녹음 듣자) , 
obp -> b = 10; //obp에 저장된 주소로 b에 접근해서 10을 저장한다.(간접 접근)
// 위와 동일한 작업이다. / 밑의 작업을 '역참조'라고 한다.
(*obp).b = 10; //.이 우선순위가 더 높아서 ()를 붙여야한다. 

직접 참조 연산자 (직접 접근 연산자)

  • 위의 코드에서 ob.b의 ‘.’을 직접 참조 연산자 라고 한다.

구조체

  • C#에서는 접근 지정자를 안붙이면 ‘public’이지만, C++은 접근지정자를 작성하지 않으면 ‘private’로 생성된다.
  • obp -> b = 10; : 간접 접근
  • (*obp).b = 10; : 직접 접근
  • Character* character2 = new Character();
    • 포인터로 동적할당을 한다면 간접 접근을 써야한다.
    • 구조체안에 int가 2개니 4바이트 + 4바이트 = 8바이트다.
  • Character* pArr = arr;
    • 포인터 변수들은 변수명 앞에 p를붙이는 경우가 많다.
    • 총 5포인트가 선언되었고 1포인트당 8바이트(4바이트 + 4바이트)다.
    • 만약 주소가 0x100부터 시작한다면 그다음 주소는 0x108번지다.
private:
	int Hp;
struct Character
{
	int Hp;
	int Mp;

};

Character character;
character.Hp = 100;
character.Mp = 50;
printf("Hp = %d, Mp = %d\\n", character.Hp, character.Mp);

Character* character2 = new Character(); //포인터로 동적할당을 한다면 간접 접근을 써야한다. / 구조체안에 int가 2개니 4바이트 + 4바이트 = 8바이트다.
character2 -> Hp = 80;
character2 -> Mp = 60;
printf("Hp = %d, Mp = %d\\n", character2 -> Hp, (*character2).Mp);

Character* character3 = &character;
character3->Hp = 200; //character의 Hp의 값이 바뀐다.
printf("Hp = %d, Mp = %d\\n", character.Hp, character.Mp);

Character arr[5];
for (int i = 0; i < 5; i++) {
	arr[i].Hp = arr[i].Mp = 0;
}

arr[0].Hp = 10;
printf("arr[0] = %d\\n", arr[0].Hp);

Character* pArr = arr; //포인터 변수들은 변수명 앞에 p를붙이는 경우가 많다. / 총 5포인트가 선언되었고 1포인트당 8바이트(4바이트 + 4바이트)다. / 만약 주소가 0x100부터 시작한다면 그다음 주소는 0x108번지다.
pArr[1].Hp = 20;
printf("arr[1] = %d\\n", arr[1].Hp);

C++의 기본

  • 시작주소? 뭐가였지? 녹음듣자
  • 배열의 뭐의 앞에 시작주소로 시작된다. Character* pArr = arr; //→ &arr[’’]

배열

  • C++에서는 배열도 ‘스택’에 할당이 가능하다.
    • int arrp[5];
  • a[1] == (*a + 1) 이다.
  • *(arr + 1) = 10;
    • 자기 자료형의 크기만큼 숫자 써있는 횟수만큼 건너뛴다.
      • 여기서는 int형이니 4바이트 건너 뛴다.
    • 현재몇번쨰 자리인지 안써있으니 0번째 자리에 적용이 되고, 결과는 arr[1]의 자리에 10이 저장된다.
  • (*arr + 1).Hp = 20;
    • arr[1]의 주소에 접근했고 그 안에있는 Hp에 20을 넣었다.
  • (arr + 2) => Hp = 20;
    • 포인터를 쓰지않고 주소로 접근해서 요소에 접근할 수 없으니 '간접 접근' (⇒)을 사용해서 값을 넣었다.
int arr[5];
arr[0] = 6;
*arr = 7; //0번자리의 6이 7로 바뀐다.
*(arr + 1) = 10; //자기 자료형의 크기만큼 숫자 써있는 횟수만큼 건너뛴다.
(*arr + 1).Hp = 20; //arr[1]의 주소에 접근했고 그 안에있는 Hp에 20을 넣었다.
(arr + 2) => Hp = 20; //포인터를 쓰지않고 주소로 접근해서 요소에 접근할 수 없으니 '간접 접근'을 사용해서 값을 넣었다.
Character* pArr = arr; //포인터 변수들은 변수명 앞에 p를붙이는 경우가 많다. / 총 5포인트가 선언되었고 1포인트당 8바이트(4바이트 + 4바이트)다. / 만약 주소가 0x100부터 시작한다면 그다음 주소는 0x108번지다.
pArr[1].Hp = 20; //a[1] == (*a + 1) 이다.
printf("arr[1] = %d\\n", arr[1].Hp);

(*(pArr + 1)).Hp = 30; //.이 *보다 우선순위가 높다보니 C의 인텔리센스에서 인식이 안된다. -> *도 괄호로 묶는다.
printf("arr[2] = %d\\n", arr[2].Hp);

pArr->Hp = 40;
printf("arr[0] = %d\\n", arr[0].Hp);

(arr + 3)->Hp = 50;
printf("arr[3] = %d\\n", arr[3].Hp);

(pArr + 4)->Hp = 60;
printf("arr[4] = %d\\n", arr[4].Hp);

클래스

  • 클래스는 접근 지정자를 아무것도 안쓰면 ‘private’로 자동 지정되어서 public: 으로 선언 해줘야한다.
  • std::string : 문자열을 다뤄주는 클래스다.
    • 이건 몇 바이트인지 모른다.(쓰는데로 늘어나기 때문이다.)
  • C에서는 static을 외부 초기화를 반드시 해줘야 한다.
  • Character* temp = new Character();
    • 스택영역에 생성되었다. -> 이것도 4바이트 아니면 8바이트다.
  • temp->Id = Character::Counting();
    • C++은 ::fh zmffotmfmf wkrtjdgksek.
    • ++이니 처음은 1이 들어간다.
  • *character = temp;
    • character는 2차 포인터다.
    • 매개로 들어온 포인터에 생성된 클래스의 객체를 연결하여 반환했다. => 2차 포인터 사용 이유
    • 2차 포인터에서 객체를 초기화하는 방식 / 모든 객체 초기화는 이렇게 진행한다.
  • Character* player = nullptr;
    • 스택에 저장된 포인터의 크기는 4바이트 아니면 8바이트다.
  • Name.c_str() : c에서 간접접근으로 문자열을 출력하는 방법
  • 객체가 초기화되는 순서
    1. Character* player = nullptr;
      1. player 포인터 메모리 공간이 스택에 생성된다.
    2. SetCharacter(&player, "Oak");
      1. 캐릭터 설정 함수를 플레이어 포인터 객체의 주소와 문자열을 넣고 호출한다.
    3. Character* temp = new Character();
      1. 지역 포인터 변수로 스택영역에 temp 공간이 생성된다.
      2. temp 포인터 변수는 새롭게 생성한 Character를 가리키는 주소를 갖고 있다.
    4. temp->Id = Character::Counting(); / temp->Name = name;
      1. ++연산이니 temp의 Id에는 1이 저장된다.
      2. temp의 Name에는 name이 저장된다.
    5. character = temp; (* 중요 **)
      1. 작성한 temp 포인터 변수를 매개변수로 들어온 character 이중 포인터 변수에 넣는다.
        1. temp에 저장된 Character 클래스 객체의 메모리 주소가 character 이중 포인터 매개변수로 넘어가고, character 이중 포인터 매개변수가 가리키는 player 포인터 변수에 다시 넘어간다.
        2. 결론적으로, temp에 있던 Character 클래스 객체 주소가 player 포인터 변수에 저장된다.
class Character
{
public:
	int Id;
	std::string Name; //std::string : 문자열을 다뤄주는 클래스다. / 이건 몇 바이트인지 모른다.(쓰는데로 늘어나기 때문이다.)

private:
	static int Number; //C에서는 static을 외부 초기화를 반드시 해줘야 한다.

public:
	static int Counting() {
		return ++Number;
	}
};
int Character::Number = 0; //외부초기화한 스테틱 변수

//이게 팩토리패턴의 기본 -> 객체 초기화를 새롭게 찍어낼 수 있기 때문이다.
void SetCharacter(Character** character, std::string name)
{
	Character* temp = new Character(); //스택영역에 생성되었다. -> 이것도 4바이트 아니면 8바이트다.
	temp->Id = Character::Counting(); //C++은 ::fh zmffotmfmf wkrtjdgksek. / ++이니 처음은 1이 들어간다.
	temp->Name = name;

	*character = temp; //character는 2차 포인터다. / 매개로 들어온 포인터에 생성된 클래스의 객체를 연결하여 반환했다. => 2차 포인터 사용 이유 / 2차 포인터에서 객체를 초기화하는 방식 / 모든 객체 초기화는 이렇게 진행한다.
}

int main() 
{
	Character* player = nullptr; //스택에 저장된 포인터의 크기는 4바이트 아니면 8바이트다.
	SetCharacter(&player, "Oak");
	printf("%d, %s\n", player -> Id, player -> Name.c_str()); //Name.c_str() : c에서 간접접근으로 문자열을 출력하는 방법

	//....

	Character* dwarf = nullptr; //스택에 저장된 포인터의 크기는 4바이트 아니면 8바이트다.
	SetCharacter(&dwarf, "Oak");
	printf("%d, %s\n", dwarf->Id, dwarf->Name.c_str()); //Name.c_str() : c에서 간접접근으로 문자열을 출력하는 바업

	//.....

	Character* elf = nullptr; //스택에 저장된 포인터의 크기는 4바이트 아니면 8바이트다.
	SetCharacter(&elf, "Oak");
	printf("%d, %s\n", elf->Id, elf->Name.c_str()); //Name.c_str() : c에서 간접접근으로 문자열을 출력하는 바업
}

'공부 > Unity' 카테고리의 다른 글

24.04.23  (0) 2024.04.24
24.04.22  (0) 2024.04.22
24.04.18  (1) 2024.04.18
24.04.17  (1) 2024.04.17
24.04.16  (0) 2024.04.16