#include <iostream>
class Knight {
protected:
int hp_;
int attack_;
int positionX_;
int positionY_;
public:
Knight(): hp_(100), attack_(1), positionX_(2), positionY_(3) { // 기본 생성자
}
Knight(const Knight& k) { // 복사 생성자
hp_ = k.hp_;
attack_ = k.attack_;
positionX_ = k.positionX_;
positionY_ = k.positionY_;
}
Knight(int hp) : hp_(hp), attack_(0), positionX_(0), positionY_(0) {} // 타입 변환 생성자 Knight k1 = 1; 도 가능하게 해줌 Kn
Knight(int hp, int attack) : hp_(hp), attack_(attack), positionX_(0), positionY_(0) {} // k = {1,2}
virtual void KnightPrint() {
std::cout << hp_ << "\n";
}
virtual void move() = 0;
};
class GeneralKnight : public Knight {
public:
void KnightPrint() {
std::cout << hp_ << ", " << attack_ << "\n";
}
void move() {
return;
}
};
int main() {
GeneralKnight k;
k.KnightPrint();
}
virtual로 가상함수를 클래스에 구현해놓으면 .vftable을 만드는데 (virtual function table) 객체를 만들시 그 메모리의 가장 상단에 vftable의 주소가 저장되는 것으로 보인다.(어셈블리어로 살펴볼 때) 그 테이블에는 virtual 함수가 선언된 순서로 저장되어 있는 것을 어셈블리어로 확인할 수 있다.
00007FF624361EB0 mov rax,qword ptr [this]
00007FF624361EB7 lea rcx,[Knight::`vftable' (07FF62436BC98h)]
Knight클래스를 상속받는 GeneralKnight 는 생성시
Knight클래스를 생성하고 그 뒤에 자기자신을 생성하는데
높은 주소 ----------------------------------------------------------------------------------------------
[vftable의 주소]
----------------------------------------------------------------------------------------------
[부모 멤버]
----------------------------------------------------------------------------------------------
[자식 멤버]
낮은 주소 ----------------------------------------------------------------------------------------------
로 메모리에 저장되는 것을 볼 수 있다.(main에 생성했기 때문에)
여기서
높은 주소 ----------------------------------------------------------------------------------------------
[vftable의 주소] <- 부모의 vftable의 주소
----------------------------------------------------------------------------------------------
[부모 멤버]
----------------------------------------------------------------------------------------------
로 부모클래스가 메모리에 할당되고 자식클래스가 생성될 때
높은 주소 ----------------------------------------------------------------------------------------------
[vftable의 주소] <- 자식의 vftable의 주소
----------------------------------------------------------------------------------------------
[부모 멤버]
----------------------------------------------------------------------------------------------
[자식 멤버]
낮은 주소 ----------------------------------------------------------------------------------------------
이렇게 vftable을 자식의 vftable의 주소로 덮어쓰고 멤버밑에 자식 멤버들을 할당한다.
또한 초기화 리스트는 클래스에서 생성자에 선처리 영역에서 초기화를 하기위해 사용되는 것인데
보통 const 상수, &참조, 아니면 부모 클래스의 기본생성자 이외의 생성자를 호출하기 위해서 또는 부모 클래스에 has-A 관계가 있는 클래스의 기본 생성자 이외의 생성자를 호출하기 위해 사용된다.