【问题标题】:Order of Class Definitions in C++C++ 中类定义的顺序
【发布时间】:2025-11-28 10:20:06
【问题描述】:

我这里有点问题。我正在尝试定义几个类,其中一些是玩家,一些是属于玩家的 Pawn。来自 Python,我习惯于通过 Pawn 方便地访问 Pawn 拥有的 Player,以及通过 Player 访问 Player 的 Pawns。如果我错了,请纠正我,但这在 C++ 中似乎是不可能的。

我目前首先定义 Player,它的一个数据成员 m_Pawns 应该是 vector<Pawn>。我声明了数据成员,但我没有为它分配任何值。我还定义了一个成员函数,用于将棋子向量分配给m_Pawns,但我不会在构造函数附近的任何地方调用它。因为我实际上并没有在Player 的构造函数中调用Pawn 的构造函数,所以看来我应该没问题。

这是我的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;
    }
}

【问题讨论】:

标签: c++ class pointers reference definition


【解决方案1】:

如果 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 类需要显示完整定义来声明对象。

唯一的出路是重新格式化您的代码或使用指针/引用(使用前向声明)。

【讨论】:

  • 您的示例既不显示指针,也不显示引用,也不显示值。它声明了一个向量到...。您可以很好地使用前向声明的类型名作为模板参数。例如。一种实现 pimpl 类型的方法:class FooImpl; class Foo { boost::shared_ptr&lt;FooImpl&gt; impl_; }
  • 另外:引用向量是不可能的。引用不是可复制的类型。
  • 我尝试翻转事物,以便首先定义 Pawn,并且只需要一个指向 Player 的指针(作为初始数据成员以及在构造函数中),但我仍然收到相同的错误消息.无论如何我都必须使用前向声明,即使使用指针?
  • @GarricW,是的,在这种情况下使用指针或引用是必须的前向声明。
  • 好吧,我想我已经做好了一切。只剩下一个小错误,我似乎无法清除。这条线有什么问题? board 是一个引用,this* 应该是指向使用该函数的 Player 实例的指针。 m_Pawns.push_back(Pawn(board.Cluster2[i], this*, m_Color));。我得到一个 expected primary-expression before ',' token 和同样的错误 '('.
【解决方案2】:

类 Pawn 仍然必须定义,以便编译后可以实例化向量。您可以在向量中存储指向 Pawn 对象的引用或指针而不是值;以向量为例。在这种情况下,Pawn 类的前向声明就足够了。

【讨论】:

    【解决方案3】:

    可以切换它,因为你可以转发声明Player,然后Pawn可以有一个指向它的指针。

    可以获取指向不完整类型的指针。你不能持有那种类型的值。

    【讨论】:

      【解决方案4】:

      你可以这样做:

      class Pawn;
      
      class Player {
      }
      
      class Pawn {
      }
      

      【讨论】:

      • 也忘了说应该怎么做。这称为前向声明。 parashift.com 对 C++ 有全面的参考。
      最近更新 更多