[C++] 📂. 객치지향 프로그래밍 (1)
0. 절차지향 프로그래밍 vs 객체지향 프로그래밍
- 절차지향 프로그래밍(Procedural Programming) :
함수
를 중심의 프로그래밍 방법 (c) - 객체지향 프로그래밍(Object Oriented Programming) :
객체
를 중심으로 돌아가는 프로그래밍 방법 (c++, c#, java …)
1. 클래스와 객체
1.1. 클래스(Class)란?
- 객체(object)를 정의하는
틀
혹은설계도
멤버 변수(state) + 멤버 함수(behavior)
으로 구성됨- 클래스는 컴파일이 끝나면
사라짐
class Knight
{
// 생성자와 소멸자
public:
Knight();
~Knight();
// 멤버 함수(기능, 동작)
public:
void Move(int y, int x);
void Attack();
void Die() { /* Die 구현 */ }
// 멤버 변수(속성, 데이터)
private:
int m_hp;
int m_attack;
int m_posY;
int m_posX;
};
void Knight::Move(int y, in x) { m_posY = y; m_posX = x; }
void Knight::Attack() { /* Attack 구현 */ }
1.2. 객체(Object, Instance)란?
- 주변의 모든 것이 객체
클래스(class)
에 의해 만들어짐- c++ 프로그램이 실행되는 동안
실존
함
int main()
{
// 객체 생성
Knight k1;
// 멤버 변수 설정
k1.m_hp = 200;
k1.m_attack = 5;
k1.m_posY = 0;
k1.m_posX = 0;
// 멤버 함수 사용
k1.Move(5, 5);
return 0;
}
2. 생성자와 소멸자
생성자(Constructor)
: 객체가 생성 될 때 실행되는 함수,1개 이상
의 생성자 존재 가능소멸자(Destructor)
: 객체가 소멸 될 때 실행되는 함수,1개만
존재
2.1. 생성자
1) 암시적(implicit) 생성자 : 생성자를 명시적으로 만들지 않으면 기본 생성자
와 기본 복사 생성자
가 자동으로 생성된다.
2) 명시적(Explicit) 생성자 : 사용자가 선언한 생성자(명시적으로 생성하면 암시적 생성은 없음)
-
기본 생성자
Knight() // *) 매개변수가 없다 { // TODO: 초기값 설정 }
Knight k0;
-
복사 생성자
Knight(const Knight& k) // *) 자신의 클래스를 참조타입 매개변수로 받음 { this.m_hp = k.m_hp; this.m_attack = k.m_attack; this.m_posY = k.m_posY; this.m_posX = k.m_posX; }
Knight k1(k0); Knight k2 = k0; // *) 복사 생성자가 아닌 경우! Knight k3; k3 = k1; // ⚠ 복사 연산자가 호출!
-
기타 생성자
Knight(int x, int y) // 기본 생성자, 복사 생성자 외 { m_posY = y; m_posX = x; }
-
타입 변환 생성자
explicit Knight(int x) {...} // 매개변수를 1개만 받는 생성자 // *) explicit가 없을 경우, 암시적으로 int 타입의 매개변수를 Knight으로 형변환 한다.
-
3. 멤버변수 초기화 방법
1) 생성자 내에서 초기화
Knight()
{
m_hp = 200;
m_attack = 5;
m_posY = 0;
m_posX = 0;
}
2) 초기화 리스트
- 상속관계에서 원하는 부모 생성자 호출 시 사용
- 멤버타입이 클래스인 경우 성능의 차이가 생김 (일반변수는 차이나지 않음)
정의함과 동시에 초기화
가 필요한 경우 사용(참조
타입,const
타입)
Knight() : m_hp(200), m_attack(5), m_posY(0), m_posX(0) { ... }
3) c++11 문법
class Knight
{
...
private:
int m_hp = 200;
int m_attack = 5;
int m_posY = 0;
int m_posX = 0;
};
3.1 활용 예시
class Player // 상속관계 클래스
{
public:
Player() {...}
explicit Player(int type) {...}
private:
int _type;
};
class Inventory // 포함관계 클래스
{
public:
Inventory() {...}
Inventory(int size) {...}
private:
int _size;
};
class Knight : public Player
{
public:
// 1) 생성자 내에서 초기화
Knight() { _inventory = Inventory(20); } // *) 비효율적
// 2) 초기화리스트를 활용한 객체 초기화
Knight() : _inventroy(20) {...}
// 3) 정의함과 동시에 초기화가 필요한 경우
Knight() : _refHp(_hp), _constHp(100) {...}
private:
Inventory _inventory;
int _hp;
int& _refHp; // or int& _refHp = hp;
const int _constHp; // or const int _constHp = 100;
}
댓글남기기