본문 바로가기

게임프로그래밍/C++ 게임 클라

[WinApi] 17 - Object

Object의 옳바른 복사

오브잭트를 복사를한다면 오브잭트의 내용을 복사한 사본이 필요하다

하지만 지금은 Object객체를 복사한다면 어떻게 될까?

Component 같은 경우는 원래의 주소를 가르키고 있는 오브잭트가 복사될 것 이다.

오브잭트의 주소값을 공유하고 있기 때문에 발생하는 현상이다.

 

04. Object -> CObject.h

...

public:
	CObject();
	//new
	CObject(const CObject& _origin);

	virtual ~CObject();

	friend class CEventMgr;
};

 

04. Object -> CObject.cpp

...
CObject::CObject()
	: m_vPos{}
	, m_vScale{}
	, m_pCollider(nullptr)
	, m_bAlive(true)

{
}

//new
CObject::CObject(const CObject& _origin)
	: m_strName(_origin.m_strName)
	, m_vPos(_origin.m_vPos)
	, m_vScale(_origin.m_vScale)
	, m_pCollider(nullptr)
	, m_bAlive(true)
{
	m_pCollider = new CCollider(*_origin.m_pCollider);
	m_pCollider->m_pOwner = this;
}
...

 

이렇게 하면 자동으로 컴파일러가 아래와 같이 생성해준다.

04. Object -> Player -> CPlayer.h

...
private:
    void CreateMissile();

public:
    CPlayer();
    //exam: 부모쪽아 아래와 같은 복사 생성자가 자동으로 생성될 것이다.
    CPlayer(const CPlayer& _origin)
        : CObject(_origin)
        , m_pTex(_origin.m_pTex)
    {

    }

    ~CPlayer();
};

 

씬에 새로운 객체를 한번 생성해보자면..

05. Scene -> Scene_Start -> CScene_Start.cpp

...
void CScene_Start::Enter()
{
	CObject* pObj = new CPlayer;
	pObj->SetPos(Vec2(640.f, 384.f));
	pObj->SetScale(Vec2(100.f, 100.f));
	AddObject(pObj, GROUP_TYPE::PLAYER);

	//exam: 복사생성자로 플레이어를 한번더 만듬
	CObject* pOtherPlayer = new CPlayer(*(CPlayer*)pObj);
	pOtherPlayer->SetPos(Vec2(740.f, 384.f));
	AddObject(pOtherPlayer, GROUP_TYPE::PLAYER);

	...
}
...

복사생성자를 Clone으로 구현

04. Object -> CObject.h

"= 0" 을 써서 자식객체에서 구현하도록 강제한다.

...
public:
	virtual void update() = 0;
	virtual void finalupdate() final;
	virtual void render(HDC _dc);
	void component_render(HDC _dc);

	//new: 자기 자신을 복사해서 되돌려주는 함수
	virtual CObject* Clone() = 0;
...

 

04. Object -> Player -> CPlayer.h

자식 객체에서 클론 함수를 구현

...
private:
    void CreateMissile();

    //new
    CPlayer* Clone() { return new CPlayer(*this); }
...

 

04. Object -> Monster -> CMonster.h

...
public:
    virtual void update();
    virtual void render(HDC _dc);
    
    //new
    CMonster* Clone() { return new CMonster(*this); }
...

 

05. Object -> Missile -> CMissile.h

미사일은 굳이 복사생성자를 해야할까..?

...
public:
	virtual void OnCollisionEnter(CCollider* _pOther);

	//new: 미사일은 얕은복사로도 될거같은데.. 굳이 복사생성자를..?
	CMissile* Clone() { return new CMissile(*this); }
...

 

 

05. Scene -> Scene_Start -> CScene_Start.cpp

생성한 Clone 함수로 대체

...
void CScene_Start::Enter()
{
	CObject* pObj = new CPlayer;
	pObj->SetPos(Vec2(640.f, 384.f));
	pObj->SetScale(Vec2(100.f, 100.f));
	AddObject(pObj, GROUP_TYPE::PLAYER);

	//old
	//CObject* pOtherPlayer = new CPlayer(*(CPlayer*)pObj);
	//new: pObj->Clone은 가상함수라 자식객체께 호출된다.
	CObject* pOtherPlayer = pObj->Clone();
    
	pOtherPlayer->SetPos(Vec2(740.f, 384.f));
	AddObject(pOtherPlayer, GROUP_TYPE::PLAYER);

	...
}
...

 

매크로로 모듈화

Clone이란 함수는 지금 무조건 구현하도록 강제되어 있다.

좀더 쉽게 구현하고자 한다면 매크로함수로 빼는것도 생각해보자

01. Header -> Define.h

...
#define fDT CTimeMgr::GetInst()->GetfDT()
#define DT CTimeMgr::GetInst()->GetDT()

//new
#define CLONE(type) type* Clone() {return new type(*this);}
...

 

04. Object -> Player -> CPlayer.h

...
private:
    void CreateMissile();

    //old
    //CPlayer* Clone() { return new CPlayer(*this); }
    //new
    CLONE(CPlayer);

public:
    CPlayer();
    ~CPlayer();
};

 

04. Object -> Monster -> CMonster.h

...
public:
    virtual void update();
    virtual void render(HDC _dc);
    
    //old
    //CMonster* Clone() { return new CMonster(*this); }
    //new
    CLONE(CMonster);

public:
    CMonster();
    ~CMonster();
};

 

04. Object -> Missile-> CMissile.h

...
public:
	virtual void OnCollisionEnter(CCollider* _pOther);

	//old
	//CMissile* Clone() { return new CMissile(*this); }
	//new
	CLONE(CMissile);

public:
	CMissile();
	~CMissile();
};

 

 

반응형