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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 08:13:17