C++中如何在父类对象数组中调用子类成员函数
问题解决方法
你的问题核心是对象切片:当BreakTile对象存入Tile类型的数组时,子类特有的部分会被“截断”,仅保留基类Tile的内容,导致调用activate()时始终执行基类版本。要解决这个问题,需要利用C++的多态特性,结合指针/智能指针实现。
步骤1:将基类方法声明为虚函数
首先修改Tile类,把activate()设为虚函数,同时添加虚析构函数(避免通过基类指针删除子类对象时的内存泄漏):
class Tile { protected: // 改为protected,让子类可以直接访问m_type char m_type; public: Tile() : m_type(' ') {} char getType() { return m_type; } virtual void activate() {} // 声明为虚函数,基类空实现 virtual ~Tile() = default; // 必须添加虚析构函数 }; class BreakTile : public Tile { public: BreakTile() { m_type = 'B'; // 子类构造时设置类型标识 } void activate() override { // 用override明确重写虚函数 // 这里编写BreakTile的激活逻辑 // 示例: // std::cout << "BreakTile activated!" << std::endl; } };
步骤2:改用指针/智能指针数组存储Tile
原有的Tile m_board[9][9]是对象数组,会触发切片。改用指针数组或智能指针数组(推荐智能指针,无需手动管理内存):
方案A:使用std::unique_ptr(推荐)
#include <memory> class Board { private: std::unique_ptr<Tile> m_board[9][9]; public: Board() { // 初始化棋盘,示例:偶数坐标设为BreakTile for (int y = 0; y < 9; y++) { for (int x = 0; x < 9; x++) { if (y % 2 == 0 && x % 2 == 0) { m_board[y][x] = std::make_unique<BreakTile>(); } else { m_board[y][x] = std::make_unique<Tile>(); } } } } // 禁止拷贝构造和赋值,避免unique_ptr的所有权冲突 Board(const Board&) = delete; Board& operator=(const Board&) = delete; void activate(int y, int x) { // 先做边界检查 if (y < 0 || y >= 9 || x < 0 || x >= 9) return; // 方法1:通过类型标识判断 if (m_board[y][x]->getType() == 'B') { m_board[y][x]->activate(); // 多态调用子类方法 } // 方法2:用dynamic_cast直接判断对象类型(更规范,无需依赖m_type) // BreakTile* breakTile = dynamic_cast<BreakTile*>(m_board[y][x].get()); // if (breakTile != nullptr) { // breakTile->activate(); // } } };
方案B:使用原始指针(需手动管理内存)
class Board { private: Tile* m_board[9][9]; public: Board() { for (int y = 0; y < 9; y++) { for (int x = 0; x < 9; x++) { m_board[y][x] = (y%2==0 && x%2==0) ? new BreakTile() : new Tile(); } } } ~Board() { // 手动释放所有内存 for (int y = 0; y < 9; y++) { for (int x = 0; x < 9; x++) { delete m_board[y][x]; } } } Board(const Board&) = delete; Board& operator=(const Board&) = delete; void activate(int y, int x) { if (y < 0 || y >=9 || x <0 || x >=9) return; if (m_board[y][x]->getType() == 'B') { m_board[y][x]->activate(); } } };
内容的提问来源于stack exchange,提问作者Lucas Alexander
相关产品推荐
相关产品推荐

