C++

14. OOP Class & Object (1)

Kelvin의 게임개발 2024. 2. 22. 18:21
728x90
반응형

1. OOP

 

OOP란 Object Oriented Programming으로 객체 지향 프로그래밍을 의미한다
 
절차 지향 프로그래밍 (Procedural Programming)은 함수를 중심으로 프로그래밍 하는 방식이다 따라서 함수들의 집합이라고 볼 수 있다
절차 지향 프로그래밍에서 데이터는 함수에서 분리되어 선언되고 데이터를 함수에서 사용해야 하면 해당 함수로 데이터를 전달해서 사용한다
절차 지향 프로그래밍의 한계점은 함수가 데이터의 구조에 대해 알아야 한다는 점이다 -> 데이터 구조가 변경되면 이 데이터를 사용하는 함수들도 전부 다 변경되어야 한다 (추후에 프로그램이 커지면 복잡해짐)

 

프로그램의 크기가 커질수록 절차 지향 프로그래밍의 한계점은 더욱 드러나게 되는데 프로그램이 커질수록 절차 지향 프로그램은 이해하기 어렵고, 유지와 확장이 어렵다, 또한 디버깅, 코드 재사용성이 좋지 않으며 다른 기능을 추가하거나 버그를 수정할 때 다른 부분에서 깨질 가능성이 높다
 
객체 지향 프로그래밍이란 객체를 중심으로 소프트웨어를 설계하는 것이다

 

프로그램이 복잡해질수록 추상화 하는것이 굉장히 중요한데 Class를 이용하여 추상화가 가능하다 ex) damage, hp, mp등을 Enemy Class에 묶어서 관리한다

 

절차 지향과 다르게 데이터가 변경되면 Class의 데이터만 변경하면 되기 때문에 쉽게 관리가 가능하다

 

객체 지향의 특징은 캡슐화, 상속성, 다형성이 있다

 

캡슐화란 객체의 데이터, 그 데이터를 처리하는 로직을 한 곳에 묶어서 캡슐로 관리하고 외부에서 직접적으로 접근할 수 없으며 클래스 외부에서 내부 데이터 처리 로직을 몰라도 사용가능하게 만드는 것을 의미한다 -> 유지보수 편의성, 이식성, 재사용성이 좋아지며 데이터 변경시 함수를 통해 하기 때문에 실수를 줄일 수 있다

 

상속성은 기존에 존재한 클래스를 부모클래스로 하여 새로운 자식 클래스를 만드는 것이다 -> 부모 클래스의 코드를 그대로 사용할 수 있기 때문에 코드의 재사용성이 좋아진다

 

다형성은 같은 이름의 함수를 여러개 선언하여 사용할 수 있게 하는것이다
하나의 클래스의 내부에 동일한 이름의 함수를 만들어 함수의 타입을 다르게 하거나, 파라미터의 개수를 다르게 하여 오버 로딩(overloading)할 수 있고 상속받은 함수를 재정의 하는 오버 라이딩(overriddng)도 할 수 있다
 
객체 지향의 단점은 실행 속도가 상대적으로 느린점, 설계시 많은 시간과 노력이 필요하다는 점이다

 

 

2. Class & Object

 

Class는 Data, Function을 가지고 있으며 사용자 정의 데이터 타입이 될 수 있다 또한 Class는 데이터와 함수를 숨길 수 있으며 접근할 수 있는 public한 interface를 제공한다
 
Object란 Class로부터 생성되며 Class의 특정 instance를 나타낸다 ex) Monster Class로 만든 AMonster, BMonster들은 Monster Class의 Instance가 된다


Object는 아주 많이 생성이 가능하며 각각의 Object는 자신만의 ID를 갖는다, 또한 Object들은 Class의 변수,함수들을 사용할 수 있다

 

 

3. Declare Class & Create Object

 

클래스 선언은 다음과 같은 방식으로 한다

class 클래스이름 //클래스 이름은 대문자로 시작
{
	클래스의 속성(데이터), 함수를 정의한다 (변수, 함수)
};
class Player
{
	//속성 (데이터)
	string name;
	int health;
	int xp;

	//함수
	void Talk(string InText);
	bool IsDead();
};

 

class는 사용자 정의 타입이기 떄문에 일반 타입과 같은 방식으로 사용이 가능하다

 

class를 이용한 Object Instance생성 방법은 다음과 같다

int main()
{
	//Object Instance 생성
	Player Kelvin;
	Player Jacob;

	//class타입도 마찬가지로 new를 통해 heap 동적할당으로 Object Instance 생성이 가능하다
	Player* TestPlayer = new Player();
	
	delete TestPlayer;

	Player Players[]{ Kelvin, Jacob }; //class타입은 배열로도 사용이 가능하다
	
	vector<Player> PlayerVec{ Kelvin }; //class타입은 vector로도 사용이 가능하다
	PlayerVec.push_back(Jacob);

	return 0;
}

 

 

4. Access Class Member

  
Class의 member에 접근하기 위해서는 .이나 ->를 사용해야 한다

 

Class타입의 일반 변수일 경우 .을 통해 멤버에 접근할 수 있다

 

Class타입의 포인터 변수일 경우 ->을 통해 멤버에 접근할 수 있다 혹은 (*Class포인터변수).으로도 접근이 가능하다
 
접근한 멤버 변수는 수정이 가능하다
 
이때 생성된 Object Instance는 Class로 부터 생성된 각각의 Specific한 Object이다 따라서 멤버 변수를 변경해도 다른 Object의 변수는 변경되지 않는다 (각각의 Object는 독립적이다)

int main()
{
	Player Kelvin;
	Player Jacob;

	Player* TestPlayer = new Player();
	
	Kelvin.name;
	Kelvin.Talk("Kelvin");

	(*TestPlayer).name;

	TestPlayer->name;
	TestPlayer->IsDead();

	return 0;
}

 

 

5. Access Modifier

 

접근지정자는 public, private, protected 3개로 나눌 수 있다

 

public: 멤버는 어디서든 접근이 가능하다, private: 멤버는 자기 자신 클래스나 friend 클래스에서만 접근이 가능하다, protected: 멤버는 상속관계에 있는 클래스에서만 접근이 가능하다
 
접근 지정자는 public: private: protected:로 작성 후 밑에 변수,함수를 선언하여 사용한다, 여러개의 접근 지정자를 사용할 수 있다
 
접근할 수 없는 멤버에 접근을 시도하면 컴파일에러가 발생한다 따라서 public function을 통해서 접근할 수 없는 변수에 접근해야 한다 ex) Get/Set()
 
외부에서 접근하면 안되는 데이터,함수와 접근해도 되는 데이터,함수를 잘 구분해서 사용해야 한다

class Player
{
public: //어디에서든 접근 가능
	string name;
	int health;
	
protected: //Player를 상속받은 클래스에서만 접근 가능
	int xp;

private: //Player 자기자신 클래스에서만 접근 가능
	void Talk(string InText);
	bool IsDead();
};

 

 

6. Implement Member Method

 

클래스 멤버 함수를 선언하는 방식은 일반 함수를 선언할 때와 동일하다 하지만 구현부는 반환형 클래스명::함수명(매개변수) { 구현; }으로 처리해야 한다

 

클래스명::을 붙히는 이유는 해당 함수가 명시된 클래스 내부에서 선언되었다는 걸 컴파일러에게 알려주기 위함이다
 
파일이 커질수록 하나의 파일에서 모든 코드를 관리하기는 힘들다 따라서 C++은 여러개의 .h와 .cpp파일로 분리해서 프로젝트를 구성한다 이때 cpp파일은 항상 해당 클래스.h를 include해야 한다

 

파일을 분리하게 되면 .h파일을 include해야 .cpp에서 해당 파일의 함수나 변수를 사용할 수 있는데 이때 동일한 .h파일을 중복으로 include하게 되면 문제가 발생한다 이를 방지하기 위해서는 #pragma once 전처리 지시문을 선언해주면 된다

 

또 다른 방법으로는 Include Guard를 해주는 방법이다 #ifndef, #define ,#endif를 사용하여 만약 해당 심볼이 정의되지 않았다면 해당 심볼을 정의하고 정의가 되었다면 #endif로 넘어가게 된다 이때 심볼 정의는 처음에 한번만 안되어 있기 때문에 단 한번만 .h파일을 include하게 되는 방식이다
 
원하는 로컬 헤더 파일을 include하고 싶다면 #include "클래스명.h"으로 include가 가능하다 (iostream이나 string같은 System Header File은 <> 사용해야 함)
 
.h파일에는 다른 .h파일을 include하는 방식을 거의 사용하지 않고 전방선언으로 처리해주는게 좋다 (cpp에만 다른 .h파일 include 처리)
 
.h파일 include는 .h의 코드를 그대로 복사 봍혀넣기를 한다고 생각하면 편하다
 
이렇게 많은 .h, .cpp파일들은 컴파일 과정에서 exe파일로 Link된다

 

//Account.h을 한번만 include되게 하기 위해서 사용한 Include Guard
#ifndef _ACCOUNT_H_ //Account.h가 심볼이 정의되지 않았다면
#define _ACCOUNT_H_ //Account.h 심볼 정의

using namespace std;
#include <iostream>

class Account
{
private:
	double balance;

public:
	void SetBalance(double InBalance);

	double GetBalance();
};

#endif //Account.h 심볼이 정의 되었다면 더 이상 정의하지 않고 넘어간다
//Account.h을 한번만 include되게 하기 위해서 사용한 #pragma once
#pragma once //동일한 .h를 한번만 include하게 해준다
#include <iostream>

using namespace std;

class Account
{
private:
	double balance;

public:
	//class 멤버함수 선언 (일반 함수 선언과 동일)

	void SetBalance(double InBalance);

	double GetBalance();
};
#include "Account.h" // " "는 해당 프로젝트 로컬 헤더 파일을 include할 때 사용한다, .cpp에서는 해당 클래스.h를 항상 include해주어야 한다

//Class 멤버함수 정의

double Account::GetBalance()
{
	return balance;
}


void Account::SetBalance(double InBalance)
{
	balance = InBalance;
}

 

//StudyCPP.cpp

#include <cctype> //<>는 System 헤더 파일을 include할때 사용한다
#include "Account.h" //StudyCPP Class에서 Account 클래스를 사용하기 위한 .h파일 include

using namespace std;

int main()
{

	return 0;
}

 

 

 

 

728x90
반응형

'C++' 카테고리의 다른 글

15. Constructor & Destructor (1)  (5) 2024.04.03
13. Pointer And Reference (2)  (62) 2024.02.14
12. Pointer And Reference, Memory Allocate (1)  (107) 2024.01.30
11. Function (2)  (108) 2024.01.26
10. Function (1)  (127) 2024.01.25