프로그래밍 언어/C++

[게임 프로그래머 입문 올인원] 객체지향 : 객체지향 개론 (27강)

순정법사 2023.09.11

A. 객체지향 개론

1. 절차 지향적 프로그래밍

a. C 언어와 함수

c언어 = 절차 지향 프로그래밍 언어

👉 절차 지향 언어에서 가장 중요한건 게임을 진행시키는 요소가 '함수' 라는 것 

 

코드가 방대해지면 나중에 공용으로 함수를 사용하지 못하게 되는 경우가 생기고

언제부턴가는 함수 만으론 관리가 어려워진다

 

knight만 받을 수 있는 HealMe

 

 

2. 객체 지향적 프로그래밍, Class

a. Class의 기초

위와 같은 문제점 때문에 객체 지향 프로그램이 생성됨

 

객체 지향으로 주로 Class를 사용한다

 

⏳ 예제 : KNight의 class를 생성

#include <iostream>
using namespace std;

//어떠한 영역도 차지 X
class Knight {
	//멤버 함수 영역은 code 영역에 들어감
public:
	void Attack() { cout << "Attack " << endl; }
	void Die() { cout << "Die " << endl; }
	void HealMe(int value) { _hp += value; }

public:
	//멤버 변수는 stack 영역에 들어감
	int _hp;
	int _attack;
	int _defence;
};

int main()
{
	//stack 영역에 생성 
	Knight k1;

	k1._hp = 100;
	k1._attack = 10;

	k1.Attack();
	k1.Die();
    	k1.Healme(30);
}

 

📝 예제 설명

 

  • class는 안에 public: 으로 멤버 함수(로직), 멤버 변수(데이터)를 사용할 수 있음
  • class는 code영역에 저장되고 멤버 변수는 class가 어디에 인스턴스로 생성되는지에 따라 위치가 달라짐
  • 호출된 k1 인스턴스는 .멤버함수와 .멤버변수로 사용할 수 있음
  • 멤버 변수와 멤버 함수의 위치는 유동적, 하지만 멤버 변수의 위치가 아래가 일반적 (C++기준)
  • 멤버 함수에서 내 자신에 대한 주소를 알고 싶다면 this를 사용할 수 있음

 

🎨 데이터의 도식화

 

멤버 변수는 class가 선언되는 위치에 따라 달라진다

 

b. 멤버 함수의 this

사실 위 코드의 HealMe()를 함수로 작성하게 된다면 아래와 같음

k1을 포인터로 받아 hp값을 수정해준것

 

void HealMe(Knight* thisPtr, int value) {
	thisPtr->_hp += value;
}

%= 위 코드와 아래 코드가 유사

class Knight {
public:
	void HealMe(int value) { 
		Knight* thisPtr = this;
		this->_hp += 10; //this-> 생략 가능 
	}

 

class에서는 위와같이 포인터로 객체를 따로 받아줄 필요 없이,

객체의 매소드를 사용할때, 그 인스턴스를 자기자신 this로 받아 수정할 수 있는 것 (주소값을 간접적으로 받는다)

따라서 위와 같은 코드가 탄생함

 

c. 파일 분리

위 코드의 파일 분리를 해보자

 

  1. 먼저 Class 파일을 생성함 이름은 Player로 수정
  2. 헤더파일에는 Class의 선언만 저장
  3. cpp파일에 구현 함수를 ctrl + .으로 단축키를 이용해 생성하고 작성해준다

 

🔎 코드 : Player.h

#pragma once

class Player {
	//멤버 함수 영역은 code 영역에 들어감
public:
	void Attack();
	void Die();
	void HealMe(int value);

public:
	//멤버 변수는 stack 영역에 들어감
	int _hp;
	int _attack;
	int _defence;
};

 

🔎 코드 : Player.cpp

#include "Player.h"
#include <iostream>
using namespace std;

//전역함수라는 의미가 아닌 
//Class의 메소드라는 의미로 ::를 붙여야 함
void Player::Attack()
{
	cout << "Attack" << endl;
}

void Player::Die()
{
	cout << "Die" << endl;
}

void Player::HealMe(int value)
{
	_hp += value;
	cout << "Heal " << _hp << endl;
}

 

분리한 코드를 연결해서 실행해보면 잘 나온당!!

 

✨ 실행결과

Attack
Die
Heal 130

 

d. 생성자 (constructor) 

1) 기본 생성자

 

 🌟 class의 객체를 생성할 때 무조건 실행되는 매소드 

 

  • 함수는 함수인데 리턴타입 X
  • 함수의 이름은 클래스의 이름과 동일
  • 함수 오버로딩처럼 여러개 생성할 수 있음 (기타 생성자)
  • 초기값을 세팅할 때 사용, 생성한 멤버 변수의 초기값을 세팅하는 용도 (세팅 안하면 쓰레기값)

 

📘 문법

class AAA{
public :
	//생성자
    AAA(){
    	
    }
}

 

2) 기타 생성자

 

🌟 기본 생성자에 함수 오버로딩처럼 생성되는 기타 생성자

 

  •  인스턴스를 자기자신 this로 받아 수정하는 것
  • 💥 만일 기타 생성자를 생성하면 기본 생성자를 제공하지 않음
  • 기타 생성자의 매개변수와 멤버 변수의 변수값이 헷갈릴 수 있으므로 항상 멤버 변수의 변수값에 _, m 등 다른 값인지 알 수 있도록 해야함

 

📘 문법 같은 예제

class Knight {
	//기타 생성자
	Knight(int hp, int attack, int defence) {
		_hp = hp;	//this-> 코드 생략 가능
		this->_attack = attack;
		this->_defence = defence;
	}

 

💙 생성자 사용 방법

동일하진 않지만 아래와 같이 다양한 방법으로 객체를 생성할 수 있음

Knight k1(100, 10, 1);
Knight k1 = Knight(100, 10, 1);
Knight k1{100, 10, 1};

 

3) 복사 생성자

 

🌟 동일한 타입의 객체를 복사해 동일한 타입의 다른 객체로 만드는 것

 

복사된 객체는 당연하지만 독립적인 행동을 할 수 있음

👉 따라서 멤버 변수들은 특정 객체에 종속적!!

 

📘 문법 같은 예제

//복사 생성자
Knight(const Knight& other) {
    this->_hp = other._hp;
    this->_attack = other._attack;
    this->_defence = other._defence;
}


...


int main()
{
	Knight k1(100, 10, 1);
	Knight k2(k1);
    
    ...
}

 

e. 소멸자 (destructor)

🌟 class의 객체가 소멸될 때 무조건 실행되는 메소드

 

값을 정리할 때 사용 👉 메모리 누수를 체크하기에 매우 좋음!!

 

📘 문법

class AAA{
public :
	//소멸자
    ~AAA(){
    	
    }
}

 

f. struct vs class 

c#과 c++의 차이점 : struct는 무조건 복사 타입, class는 참조 타입으로 등장하지만 c++에서는 거의 비슷함

 

  • struct는 상속 접근 연산자 public: 이 생략
  • class는 상속 접근 연산자 private: 이 생략되어 있음

 

⏳ 예제 : struct와 class의 차이점

#include <iostream>
using namespace std;

struct Knight1 {
public: //(생략되어 있음)
    int hp;
};

class Knight2 {
private:    //(생략되어 있음)    
            //public: 으로 사용하면 k2.hp = 10 사용가능
    int hp;
};

int main() {
    Knight1 k1;
    k1.hp = 10;

    Knight2 k2;
    k2.hp = 10;	//따라서 k2.10는 private 변수라 이렇게 사용할 수 없음
}

 

🌟 따라서 struct 는 여러 데이터를 모아 관리하기 위한 용도로 사용 

class는 객체지향 용도로 사용하면 됨!

 

 

 


출처 : https://www.inflearn.com/course/%EA%B2%8C%EC%9E%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8-%EC%9E%85%EB%AC%B8-%EC%98%AC%EC%9D%B8%EC%9B%90-rookiss#curriculum

 

[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버 -

어디부터 시작할지 막막한 게임 프로그래밍 입문자를 위한 All-In-One 커리큘럼입니다. C++, 자료구조/알고리즘, STL, 게임 수학, Windows API, 게임 서버 입문으로 이어지는 알찬 커리큘럼으로 게임 프

www.inflearn.com