0

基本抽象クラス (エンティティ) へのポインターのリストがあります。

std::list<Entity*> m_entities;

このクラスを反復処理するための typedef を作成しました

typedef std::list<Entity*>::const_iterator entityIter;

次に、リスト内の各ポインターを反復処理します

for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    const Entity &e = *i;    // ERROR
    e.DoStuff();
}

各ポインタを参照しようとすると、次のエラーが発生します

IntelliSense: "Entity *const" から "Entity" に変換するための適切なコンストラクターが存在しません

私は間違って何をしましたか?

編集:

std::shared_ptr を使用しようとしました

std::list<std::shared_ptr<Entity>> m_entities;

この方法でリストに追加することはできませんが

Entity::Entity(Game *game) 
    : m_game(game)                  
{
    m_game->g_idGenerator->generateNewID();

    m_game->m_entities.push_back(this);      // ERROR
}

以下を使用して

m_game->m_entities.push_back(std::shared_ptr<Entity>(this));

このエラーが表示されます

エラー C2664: 'void std::list<_Ty>::push_back(_Ty &&)': パラメーター 1 を >'Entity' から 'std::tr1::shared_ptr<_Ty> &&' に変換できません

編集2:

現在のコードのまとめ

for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    // *i dereferences the iterator and returns an Entity*
    // **i would additionally deference the pointer
    // Adding 'const' infront of Entity means that I can't alter the Entity
    Entity &e = **i;

    e.draw(dt);   // Causes access violation error with standard pointers
}   

上記のコードによって引き起こされるエラーを回避するかどうかを確認するために、 std:shared_ptr への変換を試みました。

ただし、エンティティを std::shared_ptr のリストに追加する際に問題が発生しています

    m_game->m_entities.push_back(std::shared_ptr<Entity>(this));

要約すると、標準ポインターでアクセス違反エラーが発生し、shared_ptr でリストに追加できません。

リストへの入力は、基本エンティティ クラスのコンストラクターを介して行われます。

Entity::Entity(Game *game) 
    : m_game(game)                  
{
    m_game->g_idGenerator->generateNewID();

            // shared_ptr version
    m_game->m_entities.push_back(std::shared_ptr<Entity>(this));  // ERROR C2664

            // raw pointer version
            //m_game->m_entities.push_back(this);  // ACCESS VIOLATION ERROR when calling methods
}
4

2 に答える 2

13
const Entity &e = *i;

*iイテレータを逆参照し、Entity* を返します。

**iさらにポインタを尊重します。

参照を保持しないようにするには、次を使用できます(*i)->memberFunction(...);

operator newエンティティを割り当てた場合は、それらにも必要であることを忘れないでくださいoperator delete

std::shared_ptrこれは、ページで説明するにはコードが複雑に見えるため、使用する例です。

自明なEntityクラスを作成し、 で使用しましたstd::shared_ptr。この情報をリストにコピーするなど、この情報を管理するstd::shared_ptr<Entity>デモンストレーションのために、同じものを複数回入れました。std::shared_ptr

#include <memory>
#include <iostream>
#include <string>
#include <list>
using namespace std;

class Entity {
private:
  string name;
public:
  Entity(const std::string& n) :
    name(n)
  { }

  const string& getName() {
    return name;
  }
};

int main(int argc, char** argv) {
  list<shared_ptr<Entity> > l;

  shared_ptr<Entity> sp(new Entity("Repeated!"));

  l.push_back(sp);
  l.push_back(sp);
  l.push_back(shared_ptr<Entity>(new Entity("Foo")));
  l.push_back(sp);
  l.push_back(shared_ptr<Entity>(new Entity("Bar")));
  l.push_back(sp);

  for(list<shared_ptr<Entity> >::const_iterator iter = l.begin();
      iter != l.end(); ++iter)
    {
      cout << ">> " << (*iter)->getName() << endl;
    }
};

std::shared_ptr注: まったく同じ生ポインタを複数のオブジェクトに配置することと、aをそのままコピーすることには違いがあります。後者の場合は完全に管理されていますが、前者の場合はそれぞれが独立して管理しようとしています。std::shared_ptrpush_backstd::shared_ptrstd::shared_ptr

于 2012-09-18T20:53:36.413 に答える
2

オプション A) 要素にアクセスし、それらを変更しないことを保証したい:

typedef std::list<Entity*>::const_iterator entityIter;

std::list<Entity*> m_entities;
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    const Entity &e = **i;    // ERROR
    e.DoStuff();
}

オプション B) 要素にアクセスして変更したい:

typedef std::list<Entity*>::iterator entityIter; // no const_

std::list<Entity*> m_entities;
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    Entity &e = **i;    // ERROR
    e.DoStuff();
}
于 2012-09-18T21:04:55.767 に答える