A. 객체지향 개론
1. 절차 지향적 프로그래밍
a. C 언어와 함수
c언어 = 절차 지향 프로그래밍 언어
👉 절차 지향 언어에서 가장 중요한건 게임을 진행시키는 요소가 '함수' 라는 것
코드가 방대해지면 나중에 공용으로 함수를 사용하지 못하게 되는 경우가 생기고
언제부턴가는 함수 만으론 관리가 어려워진다
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를 사용할 수 있음
🎨 데이터의 도식화
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. 파일 분리
위 코드의 파일 분리를 해보자
- 먼저 Class 파일을 생성함 이름은 Player로 수정
- 헤더파일에는 Class의 선언만 저장
- 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는 객체지향 용도로 사용하면 됨!
'프로그래밍 언어 > C++' 카테고리의 다른 글
[게임 프로그래머 입문 올인원] 객체지향 : 멤버 변수 초기화 (31강) (0) | 2023.09.11 |
---|---|
[게임 프로그래머 입문 올인원] 객체지향 : OOP 3대 요소 / 상속성, 은닉성, 다형성 (28, 29, 30강) (0) | 2023.09.11 |
C++ 문자열 총정리 (0) | 2023.09.09 |
[자료형(data type)] C++ 파생형 포인터 총정리 (0) | 2023.09.09 |
[자료형(data type)] C++ 파생형 배열 총정리 (0) | 2023.09.08 |