C++多态开发:指针数组指针访问对象的错误排查
问题分析与修复方案
核心错误点
- 数组创建与销毁不匹配:用
new Playful[playSize]创建对象数组,却用delete hPtr[0];销毁,必须使用delete[],否则会触发内存错误(munmap_chunk(): invalid pointer)。 - 基类缺少虚析构函数:通过基类指针销毁子类对象时,若析构函数非虚函数,只会调用基类析构函数,导致子类资源未正确释放,引发内存问题。
- 子类数组的多态访问风险:直接用基类指针指向子类对象数组,若后续子类添加成员,
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)时,只需:
- 定义新子类继承
Hokeemon - 在
main中新增一组指针数组,存储新子类的对象指针 - 更新
groupCount和groupSizes即可,无需修改forEach函数,完全满足“轻松添加子类”的需求。
内容的提问来源于stack exchange,提问作者user20259078
相关产品推荐
相关产品推荐

