You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中以引用传递对象作为类参数的问题求助

问题分析与解决方案

问题根源

你遇到的核心问题是对象拷贝导致的两个独立Pawn实例:

  • 当调用board.addNewPawn(pawn)时,函数参数采用值传递,这会创建一个pawn的副本并赋值给Board内部的m_pawn。
  • 主函数中的pawn和Board中的m_pawn是完全独立的对象,地址不同,因此修改主函数中pawn的位置不会同步到Board的m_pawn。

解决方案1:使用指针共享同一个对象

通过让Board持有指向主函数中Pawn对象的指针,确保两者操作的是同一个实例。

步骤1:修改Board.h

将私有成员m_pawn改为指针类型,并更新函数签名:

#ifndef BOARD
#define BOARD
#include<vector>
#include "Pawn.h"

class Board
{
public:
    Board(int x, int y);

    void initBoard();
    void displayBoard();
    void addNewPawn(Pawn* pawn); // 修改为指针参数

private:
    std::vector<std::vector<char>> m_board;
    int m_xsize;
    int m_ysize;
    Pawn* m_pawn; // 改为指针类型
};
#endif

步骤2:修改Board.cpp

  • 初始化指针为空,避免悬空指针
  • 更新addNewPawn函数直接赋值指针
  • 在displayBoard中使用->访问指针成员:
#include <iostream>
#include <vector>

#include "Board.h"

using namespace std;

Board::Board(int x, int y): m_xsize(x), m_ysize(y), m_pawn(nullptr) // 初始化指针为空
{
}

// 保留initBoard函数不变
void Board::initBoard()
{
    for (int x=0; x<m_xsize; x++)
    {
        vector<char> newline(m_ysize);
        m_board.push_back(newline);
    }

    for (int x = 0; x < m_xsize; x++)
    {
        for (int y = 0; y < m_ysize; y++)
        {
            if (x == 0 || y == 0 || x == m_xsize - 1 || y == m_ysize - 1)
            {
                m_board[x][y] = '*';
            }
            else
            {
                m_board[x][y] = ' ';
            }
        }
    }
}

void Board::displayBoard()
{
    if (m_pawn == nullptr) return; // 防止空指针崩溃

    cout << "board pawn address " << m_pawn << endl;

    m_board[m_pawn->getXpos()][m_pawn->getYpos()] = 'o'; // 使用->访问成员
    cout << "display " << m_pawn->getXpos() << " " << m_pawn->getYpos() << endl;

    for (int x = 0; x < m_xsize; x++)
    {
        for (int y = 0; y < m_ysize; y++)
        {
            cout << m_board[x][y];
        }
        cout << endl;
    }
}

void Board::addNewPawn(Pawn* pawn)
{
    m_pawn = pawn; // 直接赋值指针,共享同一个对象
}

步骤3:修改main.cpp

传递pawn的地址给addNewPawn:

#include <iostream>
#include "Board.h"
#include "Pawn.h"
#include <conio.h>

using namespace std;

int main()
{
    Pawn pawn{ 1, 1 };
    Board board{ 20, 20 };

    board.addNewPawn(&pawn); // 传递指针
    board.initBoard();
    board.displayBoard();

    char input;
    do
    {
        input = _getch();

        int xshift = 0;
        int yshift = 0;

        if (input == 'z')
        {
            yshift = -1;
        }
        else if (input == 'q')
        {
            xshift = -1;
        }
        else if (input == 's')
        {
            yshift = 1;
        }
        else if(input == 'd')
        {
            xshift = 1;
        }
        
        cout << "pawn address " << &pawn << endl;
        pawn.movePawn(xshift, yshift);
        board.displayBoard();

    }while (input != 'x');
}

解决方案2:使用引用共享同一个对象

引用是另一种共享对象的方式,比指针更安全(不会有空指针问题),但需要在Board构造时就绑定到目标对象。

步骤1:修改Board.h

将私有成员改为引用类型,并调整构造函数参数:

#ifndef BOARD
#define BOARD
#include<vector>
#include "Pawn.h"

class Board
{
public:
    Board(int x, int y, Pawn& pawn); // 添加Pawn引用参数

    void initBoard();
    void displayBoard();

private:
    std::vector<std::vector<char>> m_board;
    int m_xsize;
    int m_ysize;
    Pawn& m_pawn; // 改为引用类型
};
#endif

步骤2:修改Board.cpp

在构造函数中初始化引用,并更新displayBoard(无需addNewPawn函数):

#include <iostream>
#include <vector>

#include "Board.h"

using namespace std;

Board::Board(int x, int y, Pawn& pawn): m_xsize(x), m_ysize(y), m_pawn(pawn) // 初始化引用
{
}

// 保留initBoard函数不变
void Board::initBoard()
{
    for (int x=0; x<m_xsize; x++)
    {
        vector<char> newline(m_ysize);
        m_board.push_back(newline);
    }

    for (int x = 0; x < m_xsize; x++)
    {
        for (int y = 0; y < m_ysize; y++)
        {
            if (x == 0 || y == 0 || x == m_xsize - 1 || y == m_ysize - 1)
            {
                m_board[x][y] = '*';
            }
            else
            {
                m_board[x][y] = ' ';
            }
        }
    }
}

void Board::displayBoard()
{
    cout << "board pawn address " << &m_pawn << endl;

    m_board[m_pawn.getXpos()][m_pawn.getYpos()] = 'o'; // 仍使用.访问成员
    cout << "display " << m_pawn.getXpos() << " " << m_pawn.getYpos() << endl;

    for (int x = 0; x < m_xsize; x++)
    {
        for (int y = 0; y < m_ysize; y++)
        {
            cout << m_board[x][y];
        }
        cout << endl;
    }
}

步骤3:修改main.cpp

创建Board时直接传入pawn的引用:

#include <iostream>
#include "Board.h"
#include "Pawn.h"
#include <conio.h>

using namespace std;

int main()
{
    Pawn pawn{ 1, 1 };
    Board board{ 20, 20, pawn }; // 传入引用

    board.initBoard();
    board.displayBoard();

    char input;
    do
    {
        input = _getch();

        int xshift = 0;
        int yshift = 0;

        if (input == 'z')
        {
            yshift = -1;
        }
        else if (input == 'q')
        {
            xshift = -1;
        }
        else if (input == 's')
        {
            yshift = 1;
        }
        else if(input == 'd')
        {
            xshift = 1;
        }
        
        cout << "pawn address " << &pawn << endl;
        pawn.movePawn(xshift, yshift);
        board.displayBoard();

    }while (input != 'x');
}

注意事项

  • 使用指针时,确保Pawn对象的生命周期长于Board对象(这里主函数中的pawn先创建,后销毁,符合要求)。
  • 使用引用时,引用一旦绑定就无法更改,因此Board必须从构造时就绑定到目标Pawn。
  • 两种方案都能实现同一个对象共享,解决位置不同步的问题,可根据你的代码结构选择。

内容的提问来源于stack exchange,提问作者Willy Lutz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:20:00