2016-07-06 7 views
0

オブジェクトが互いに認識している(つまり、すべてのオブジェクトへのポインタを持つ)クラスを作成しようとしています。スマートポインタや静的メンバーに関するこのアイデアの実装のいくつかの側面を理解できません。スマートポインタを使用してクラスのオブジェクトを追跡するにはどうすればよいですか?

クラスは、他のゲームオブジェクトのメンバー関数とプロパティにアクセスできる必要があるゲームオブジェクトと考えることができます。

私の知る限り、望ましい設計を実装する一般的な方法は、他のオブジェクトへのポインタを含む静的ベクトルです。生のポインタで動作している場合、タスクは非常に複雑ではありません。

GameObject.h:

#pragma once 

#include <vector>  

class GameObject 
{ 
private: 
    static std::vector< GameObject* > objects; 
public: 
    GameObject() 
    { 
     objects.push_back(this); 
    } 
}; 

GameObject.cpp:

#include "GameObject.h" 

std::vector< GameObject* > GameObject::objects = {}; 

これは実際に私は必要なものを与えるだろう。しかし、私がスマートポインタを使用したい場合、事は私にとっては単純ではありません。 this questionから、そしてMeyersの「Effective Modern C++」の本から、私は約std::enable_shared_from_thisshared_from_this()を見つけました。しかし、さらに、the referenceは、既にstd::shared_ptr<>が所有しているオブジェクトの場合にのみ、shared_from_this()を使用することが許可されていることを明確に示しています。

したがって、以前と同じ方法で、コンストラクタ内の静的ベクトルthisポインタ(またはその上に構築されたstd::shared_ptr)をコンストラクタにプッシュすることはできません。

GameObject.h:

#pragma once 

#include <vector> 
#include <memory> 


class GameObject : public std::enable_shared_from_this<GameObject> 
{ 
private: 
    static std::vector< std::shared_ptr<GameObject> > objects; 
public: 
    GameObject() {} 

    void emplace_ptr() 
    { 
     objects.emplace_back(shared_from_this()); 
    } 
}; 

GameObject.cpp:

#include "GameObject.h" 

std::vector< std::shared_ptr<GameObject> > GameObject::objects = {}; 

main.cppに私が分かった設計を可能にするコードの最小セットは、以下であります:

私は明らかに、オブジェクトの外側のどこかにポインタを作成し、ポインタを静的ベクタにプッシュするメソッドを明示的に呼び出すことを義務付けられています(コンストラクタでこれを行うことはできません)。

必要なコードが不必要に複雑になっているという印象を受けています(ローポインタの場合と比較して)。または無意味なことをしています。

  1. オブジェクトを互いに認識するための私の努力は意味があります ?それは一般的な問題か、他のアプローチは通常 ですか?
  2. 静的ベクトルは問題のサウンドソリューションですか?
  3. スマートポインタを使用してこのようなベクターを構築するには、どうすればよいですか? 外部からの介入なしで、 特殊機能emplace_ptr()を作成する必要はありませんか?
+2

コンストラクタ 'private'を作ることによって' enable_share_from_this'を取り除き、静的コンストラクタを提供して、ベクトルを供給することができます。 – Jarod42

+0

@ Jarod42、静的な名前のコンストラクタ(または関数を作成する)を意味すると思います。 – lorro

答えて

1

あなたが代わりにあなたが(共有)のインスタンスを作成しますstatic工場の機能を持つことができ、enable_shared_from_this必要はありませんが、ベクターにそれを置く、ともそれを返します。あなたは、例えば行うインスタンスを取得するためにその後

class GameObject 
{ 
private: 
    static std::vector<std::shared_ptr<GameObject>> objects; 

    // Don't allow creation from outside 
    GameObject() {} 

public: 
    static std::shared_ptr<GameObject> create() 
    { 
     objects.emplace_back(new GameObject); 
     return objects.back(); 
    } 
}; 

よう

何かオブジェクトがベクトルに限り、彼らがそうであるようにスコープの外に出ることは決してありません共有ポインタで指され、ベクトルの寿命は、プログラムの寿命です:

auto new_game_object = GameObject::create(); 

あり、これに一つだけの問題です(それはstaticなので)。だから、どこからいつそれらのインスタンスをベクトルから削除するか考える必要があります。

0

静的ベクトルをGameObjectクラスの外に移動し、ゲームオブジェクトを管理するコードをゲームオブジェクト自体の内部に置くことから始めます。別のユーザが提案した静的なcreate()メソッドは助けになりますが、個人的にはGameObject/Derivedゲームオブジェクトコンストラクタを自分で呼び出すことができるので、構築中に必要なデータを渡すことができます。

ゲームエンジンの実行中にオブジェクトを追加するGameObjectWorldクラスのようなものを作成します。 GameObjectコンストラクタから、自動的にそれらを世界に追加する必要はありません。あなたが何か行うことができ

:過去には

auto gameObject = std::make_shared<GameObject>(); 
// implemented at a singleton for simplicity 
GameObjectWorld::getInstance().add(gameObject); 

を、私は与えられたゲーム「パート」や「シーン」で、それはゲームオブジェクト(エンティティ)の独自のリストです維持アプローチを取ってきました自分のリストを維持する。これにより、オブジェクト階層を追加することで、それらを再帰的に操作してアクションを実行することができます。

ここで原油と簡単な例です:

class Part 
{ 
    std::vector<std::shared_ptr<GameObject> children; 
public: 
    void addChild(std::shared_ptr<GameObject> object) 
    { 
     children.push_back(object); 
    } 

    // Part lifecycle 
    virtual void onCreate() = 0; // must be provided by your parts 
}; 

class GamePart :: public Part 
{ 
    void onCreate() override; // called by your engine 
}; 

void GamePart::onCreate() 
{ 
    addChild(std::make_shared<GameObject>()); 
} 

これはあなたのゲームオブジェクトの管理を開始するための非常に簡単な方法であると私は非常に「エンティティコンポーネントシステム」上に読んで、いくつかの方法を理解することをお勧めしたいです業界の専門家がゲームの世界を管理しています。

関連する問題