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

C++多态开发:指针数组指针访问对象的错误排查

问题分析与修复方案

核心错误点

  1. 数组创建与销毁不匹配:用new Playful[playSize]创建对象数组,却用delete hPtr[0];销毁,必须使用delete[],否则会触发内存错误(munmap_chunk(): invalid pointer)。
  2. 基类缺少虚析构函数:通过基类指针销毁子类对象时,若析构函数非虚函数,只会调用基类析构函数,导致子类资源未正确释放,引发内存问题。
  3. 子类数组的多态访问风险:直接用基类指针指向子类对象数组,若后续子类添加成员,temp[j]会按基类大小计算内存偏移,必然导致访问越界(段错误)。

修复后的代码

#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>

using namespace std;

// 基类:添加虚析构函数保证子类对象正确销毁
class Hokeemon {
    friend ostream &operator<< (ostream &stream, Hokeemon &critter);
public:
    string name;
    virtual string getName(){return name;};
    virtual ~Hokeemon() = default;
};

class Playful : public Hokeemon{        
public:
    Playful() {
        cout << "Hokeemon's being hatched.\n";
        name = "Test";         
    }   
    
    ~Playful(){cout << "Hookemon deleted" << endl;};
};

// 遍历函数:适配指针数组的存储结构
void forEach(int groupCount, Hokeemon*** ptrGroups, int* groupSizes, void(*func)(Hokeemon &critter));

int main() {
    int groupCount = 1, aliveSize = 3; 
    srand(time(NULL));

    // 存储结构改为:数组元素是指向子类对象指针的数组
    Hokeemon* hPtrGroups[groupCount];
    int groupSizes[groupCount];
    
    // 创建Playful对象并存储指针
    groupSizes[0] = aliveSize;
    hPtrGroups[0] = new Hokeemon*[aliveSize];
    for(int i=0; i<aliveSize; i++){
        hPtrGroups[0][i] = new Playful();
    }

    // 调用遍历函数,传入lambda处理对象
    forEach(groupCount, &hPtrGroups[0], groupSizes, [](Hokeemon &critter){ 
        cout << critter.getName() << endl;
    });

    // 正确销毁资源:先销毁每个子类对象,再销毁指针数组
    for(int i=0; i<groupCount; i++){
        for(int j=0; j<groupSizes[i]; j++){
            delete hPtrGroups[i][j];
        }
        delete[] hPtrGroups[i];
    }

    return 0;
}

void forEach(int groupCount, Hokeemon*** ptrGroups, int* groupSizes, void(*func)(Hokeemon &critter)){
    for( int i = 0; i < groupCount; i++){ 
        Hokeemon** currentGroup = ptrGroups[i];
        for (int j = 0; j < groupSizes[i]; j++){
            func(*currentGroup[j]);
        }
    }
}

关键修改说明

  • 虚析构函数:基类Hokeemon添加virtual ~Hokeemon() = default;,确保通过基类指针销毁子类对象时,能正确调用子类析构函数。
  • 存储结构优化:改用Hokeemon**存储每个子类对象的指针,彻底避免子类数组的多态偏移错误,无论子类大小如何,都能正确访问每个对象。
  • 匹配内存操作:创建数组用new[],销毁用delete[];单个对象用new,销毁用delete,彻底解决内存错误。
  • 遍历函数适配:调整参数为Hokeemon***,对应指针数组的数组结构,遍历每个组内的对象指针,解引用后传入lambda。

扩展建议

后续添加新子类(如Aggressive)时,只需:

  1. 定义新子类继承Hokeemon
  2. 在main中新增一组指针数组,存储新子类的对象指针
  3. 更新groupCount和groupSizes即可,无需修改forEach函数,完全满足“轻松添加子类”的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:01:47