Objective Oriented Programming
카테고리: Cpp
태그: Programming
모두의 코드 씹어먹는 c++ 자료를 보고 정리한 내용입니다.
상속성
class Player
{
public:
Player()
{
hp = 0;
attack = 0;
defence = 0;
cout << "Player 생성자 호출" << endl;
}
~Player() { cout << "Player 소멸자 호출" << endl; }
void Move() { cout << "move" << endl; }
void Attack() { cout << "Attack" << endl; }
void Die() { cout << "Die" << endl; }
public:
int hp;
int attack;
int defence;
};
class Knight : public Player
{
public:
Knight()
{
hp = 0;
attack = 0;
defence = 0;
stamina = 0;
cout << "Knight 생성자 호출" << endl;
}
~Knight() { cout << "Knight 소멸자 호출" << endl; }
public:
int stamina;
};
int main()
{
Knight k;
k.hp = 100;
k.attack = 10;
k.defence = 5;
k.stamina = 10;
return 0;
}
- Knight 생성하면 → Player 생성자? Knight 생성자?
- 둘 다 호출!
- Knight() 코드 실행 전에 Player의 생성자 호출됨
- 생성자는 일반 함수와 조금 다르게 동작한다고 보는 것이 맞음
- 선처리 영역이 존재해서, 부모 클래스의 생성자가 먼저 실행
- 소멸자도 마찬가지로 작동
은닉성
은닉성 (Data Hiding) = 캡슐화 (Encapsulation) → 반드시 필요한 경우가 아니면 숨기겠다.
- 정말 위험하고 건드리면 안되는 경우
- 다른 경로로 접근하길 원하는 경우 (ex. 데이터가 변할 때마다 항상 체크해야 하는 것이 있음)
- public / protected / private
다형성 (Polymorphism)
껍데기는 똑같은데 기능이 다르게 동작
- 오버로딩 : 함수의 중복 정의 (함수 이름의 재사용)
- 오버라이딩 : 재정의(부모 클래스의 함수를 자식 클래스에서 재정의)
[바인딩 (Binding)]
- 정적 바인딩 (Static Binding) : 컴파일 시점에 결정
- 동적 바인딩 (Dynamic Binding) : 런타임 시점에 결정
Virtual Function
class Player
{
public:
Player()
{
hp = 100;
}
virtual void VMove() { cout << "player move" << endl; }
public:
int hp;
};
class Knight : public Player
{
public:
Knight()
{
stamina = 100;
}
void VMove() { cout << "knight move" << endl; }
public:
int stamina;
};
void MovePlayer(Player* player)
{
player->VMove();
}
int main()
{
Knight k;
MovePlayer(&k); // "knight move"
return 0;
}
MovePlayer(&k);
코드를 실행시에 (런타임), 컴퓨터 입장에서
“흠, player는 Player 포인터니까 Player의 VMove()를 실행해야지” “어 근데 VMove()가 virtual이네?”
“잠깐. 이거 정말 Player 객체 맞어? 아니네 Knight 객체네” “그럼 Knight의 VMove()를 실행해야지”
실제 객체가 어떤 타입인지 어떻게 알고 가상함수를 호출해줄까?
- Knight k의 주소를 찍어보면 멤버 변수 말고 이상한 값이 들어있음 → [가상 함수 정보를 들고있는 테이블 (vftable)] 존재
- 타고 들어가면 virtual function 주소들이 들어있음
- 참고로 자바는 static을 제외한 모든 함수가 virtual 함수. C++는 성능 최적화를 위해 virtual 명시하도록 설계
- player의 가상함수 테이블에 들어가서
- offset 0짜리 함수 (첫 번째 가상함수) 호출
- 가상함수 테이블은 어디서 채우지? → 생성자
- Player에서 생성해 놓은 가상함수 테이블을
- Kinght 생성자가 ==”나는 Player가 아니라 Knight야”== 하고 덮어 쓰는 방식
순수 가상 함수 (Abstract Function)
virtual void VAttack() = 0;
virtual void VAttack() abstract;
- 구현은 없고 ‘인터페이스’만 전달하는 용도로 사용하고 싶은 경우
- ` = 0 `
abstract
두 가지 방식으로 선언 - abstract function이 하나라도 포함되면 abstract class로 간주 → 직접적으로 객체를 만들 수 없게 됨 → abstract function을 구현 해야만 객체 생성 가능
댓글 남기기