Порядок определений классов в C ++ - PullRequest
5 голосов
/ 16 июня 2011

У меня тут небольшая проблема. Я пытаюсь определить несколько классов, некоторые из которых являются игроками, а некоторые - пешками, принадлежащими игрокам. Исходя из Python, я привык иметь удобный доступ к игроку, владеющему пешкой, через пешку, а также к пешкам игрока через игрока. Поправьте меня, если я ошибаюсь, но это кажется невозможным в C ++.

В настоящее время я определяю Player первым, и один из его элементов данных m_Pawns должен быть vector<Pawn>. Я объявляю элемент данных, но не присваиваю ему никакого значения. Я также определяю функцию-член, которая предназначена для присвоения вектора пешек m_Pawns, но я не вызываю его где-либо рядом с конструктором. Поскольку я на самом деле не вызываю конструктор для Pawn в конструкторе для Player, похоже, все должно быть в порядке.

Вот мой Player класс. Класс Board определен заранее, тогда как класс Pawn определен позже (класс Pawn содержит указатели на владельца класса Player, поэтому его переключение не очень помогает).

class Player
{
public:
    Player(sf::Color color, const string& name);
    sf::Color GetColor();
    string GetName();
    void CreatePawns(Board& board, int which);
protected:
    vector<Pawn> m_Pawns;
    sf::Color m_Color;
    string m_Name;
};

Player::Player(sf::Color color, const string& name):
    m_Color(color),
    m_Name(name)
{}

sf::Color Player::GetColor()
{
    return m_Color;
}

string Player::GetName()
{
    return m_Name;
}

void Player::CreatePawns(Board& board, int which)
{
    switch(which)
    {
    case 1:
        for(int i = 0; i < 4; ++i)
        {
            m_Pawns.push_back(Pawn((*board).Cluster1[i], this*, m_Color));
        }
        break;
    case 2:
        for(int i = 0; i < 4; ++i)
        {
            m_Pawns.push_back(Pawn((*board).Cluster2[i], this*, m_Color));
        }
        break;
    case 3:
        for(int i = 0; i < 4; ++i)
        {
            m_Pawns.push_back(Pawn((*board).Cluster3[i], this*, m_Color));
        }
        break;
    default:
        cout << "Invalid player ID!\n\n";
        break;
    }
}

Ответы [ 4 ]

2 голосов
/ 16 июня 2011

Если class Player идет первым, а class Pawn позже, тогда вы можете только объявить указатель или ссылку на более поздний класс (здесь Pawn). Вы не можете иметь объекты более позднего класса , например

class Player {
  Pawn* p; // allowed
  Pawn& r; // allowed
  vector<Pawn*> p; // allowed
  vector<Pawn&> vr; // not allowed (reference are not copyable)
  vector<Pawn> o; // error !
};

class Pawn {};

Нет способа преодолеть эту ситуацию, так как в C ++ для non-template класса один необходимо показать полное определение для объявления объектов.

Единственный выход - переформатировать ваш код или использовать указатель / ссылку (с предварительным объявлением ).

0 голосов
/ 17 июня 2011

Вы можете переключить его, потому что вы можете переслать декларацию Player, и тогда Pawn может иметь указатель на него.1009 * может взять указатель на неполный тип.Вы не можете хранить значения этого типа.

0 голосов
/ 17 июня 2011

Вы можете сделать что-то вроде этого:

class Pawn;

class Player {
}

class Pawn {
}
0 голосов
/ 16 июня 2011

Класс Pawn все еще должен быть определен, чтобы скомпилированный мог создать экземпляр вектора. Вы можете избежать хранения ссылок или указателей на объекты Pawn в вашем векторе вместо значений; вектор например. В этом случае будет достаточно предварительного объявления класса Pawn.

...