3

マップにオブジェクトを挿入しようとすると、次の例外がスローされます。

Main.exeの0x77a015deで未処理の例外:0xC0000005:アクセス違反の読み取り場所0x00000004。

「読み取り場所0x00000004」は、ある種のnullポインター例外だと思います。ただし、マップ自体は静的マップであり、.cppファイルで初期化されます。挿入しようとしたときに場所がないのはなぜですか?

これがクラスです。これは、プレーヤーへのマッピングIDを管理するプレーヤークラスです。

// Player.hpp
class Player {
  public:

    Player(){}; // I had to make this public, otherwise it wouldn't compile.
    Player(Player &p);
    Player & operator=(const Player &p);
    bool operator==(const Player &p);

    int getID() const;
    int getTeam() const;
    string getName() const;
    Vec3 getColor() const;

    static Player newPlayer(int team, string name, Vec3 color);

  private:
    Player(int id, int team, string name, Vec3 color);
    int id,
        team;
    string name;
    Vec3 color;

    static std::map<int, Player> players;
};

およびcppファイル:

#include "Player.hpp"
std::map<int, Player> Player :: players;
int Player :: currentPlayer=-1;

// Constructor
Player :: Player(Player &p) : id(p.getID()),
                              team(p.getTeam()),
                              name(p.getName()),
                              color(p.getColor()){}

Player & Player :: operator=(const Player &p){
  if (this==&p){
    return *this;
  }

  id=p.getID();
  team=p.getTeam();
  name=p.getName();
  color=p.getColor();

  return *this;
}

bool Player :: operator==(const Player &p){
  return p.getID()==getID();
}

// Factory
Player Player :: newPlayer(int team,
                           string name,
                           Vec3 color){
  int playerID=0;
  if (players.size()>0){
    int playerID=(*players.rbegin()).first+1; // get an ID higher than the largest already there.
  }

  Player p(playerID, team, name, color);
  players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
  return players[playerID];
}

// Internal Constructor
Player :: Player(int id,
                 int team,
                 string name,
                 Vec3 color) : id(id),
                               team(team),
                               name(name),
                               color(color){}

誰かが私がここで何が起こっているのかを理解するのを手伝ってもらえますか?

編集:このメソッドを呼び出すコードは、グローバルスコープのmain.hppにあり、メソッドの外部にあります。

Player player1=Player::newPlayer(1, "p1", Vec3(0.2, 0.2, 0.8)),
       player2=Player::newPlayer(2, "p2", Vec3(0.8, 0.2, 0.2));
4

2 に答える 2

4

パブリックデフォルトコンストラクターの必要性に対処するには、次のように変更してみてください。

Player p(playerID, team, name, color);
players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
return players[playerID];

これに:

return players.insert(std::make_pair(playerID, Player(playerID, team, name, color))).first->second;

(説明:[]-operatorでは、マップされたタイプがデフォルトで構築可能である必要があります。これを使用すると、検索しているキーがマップに存在するという知識を無視することになります。オペレーターは、新しいデフォルトで構築されたものを作成したいと考えています。指定したキーが存在しない場合は要素。)


更新: 静的初期化の問題にも対処する必要があります。これを行う1つの方法は次のとおりです。

// header:

class Player {
public:
    static std::map<int, Player> & players();
    // ...
};

// implementation:

std::map<int, Player> & Player::players()
{
    static std::map<int, Player> impl;
    return impl;
}

ここで、を使用Player::players()してマップへの参照を取得します。

于 2012-05-12T20:26:01.710 に答える
2

挿入は、他のオブジェクトの静的初期化の一部としても発生しますか?

もしそうなら、あなたは古典的なC ++の落とし穴にぶつかりました:異なるファイル間の静的初期化の順序はほとんど定義されておらず、あなたが望むことをすることはめったにありません。

于 2012-05-12T20:26:58.007 に答える