如何修改C++代码以访问对象的原始成员而非副本,实现礼物列表的更新?
问题分析与修复方案
嘿,我一眼就看出问题所在了——你现在操作的都是对象的副本,不是原始数据!这就是为什么修改后原始列表毫无变化的原因。下面给你详细拆解问题和解决步骤:
核心问题根源
你代码里的两个关键方法都是返回值拷贝,而不是直接引用原始对象:
Child::getList()返回的是ArrayList<string>的副本,不是内部那个presents列表本身;ArrayList::getEntry()返回的也是Child对象的副本,不是列表里存储的原始Child实例。
所以当你执行this->getEntry(position).getList().insert(...)时,你只是在临时创建的Child副本里修改了它的礼物列表副本,这些临时对象执行完就被销毁了,原始数据当然纹丝不动。
一步步修复代码
我们需要修改两个类的方法,让它们返回引用,这样就能直接操作原始对象:
1. 改造Child类的礼物列表访问方法
给Child添加一个返回可修改引用的getList(),同时保留只读版本(遵循const正确性):
// Child.h 中的类声明修改 class Child { private: string name; ArrayList<string> presents; public: string getName() const; // 新增:返回可修改的引用,用于修改礼物列表 ArrayList<string>& getList(); // 保留:返回只读引用,用于只需要查看的场景 const ArrayList<string>& getList() const; void setName(string name); void setList(ArrayList<string> aList); }; // 实现这两个方法 ArrayList<string>& Child::getList() { return presents; } const ArrayList<string>& Child::getList() const { return presents; }
2. 改造ArrayList的getEntry方法
同样,新增返回非const引用的版本,让我们能修改列表里的原始对象:
// ArrayList.h 中的类声明修改 template<class ItemType> class ArrayList { // ... 原有私有/保护成员不变 ... public: // ... 原有方法不变 ... // 新增:返回可修改的对象引用 ItemType& getEntry(int position) throw(PrecondViolatedExcep); // 修改原有const版本的返回类型为const引用 const ItemType& getEntry(int position) const throw(PrecondViolatedExcep); }; // 实现非const版本的getEntry template<class ItemType> ItemType& ArrayList<ItemType>::getEntry(int position) throw(PrecondViolatedExcep) { bool ableToGet = (position >= 1) && (position <= itemCount); if (ableToGet) return items[position - 1]; else { string message = "getEntry() called with an empty list or invalid position."; throw(PrecondViolatedExcep(message)); } } // 修改原有const版本的getEntry返回类型 template<class ItemType> const ItemType& ArrayList<ItemType>::getEntry(int position) const throw(PrecondViolatedExcep) { bool ableToGet = (position >= 1) && (position <= itemCount); if (ableToGet) return items[position - 1]; else { string message = "getEntry() called with an empty list or invalid position."; throw(PrecondViolatedExcep(message)); } }
3. 修正insertPresent方法
现在我们可以直接操作原始Child对象的礼物列表了,顺便优化一下逻辑(比如把礼物插在列表末尾,增加未找到孩子的判断):
template<class ItemType> bool NiceArrayList<ItemType>::insertPresent(string name, string newEntry) { bool ableToInsert = false; int length = this->getLength(); int targetPosition = -1; // 先遍历找到对应名字的Child位置 for (int i = 1; i <= length; i++) { if (this->getEntry(i).getName() == name) { targetPosition = i; break; } } // 没找到对应名字的孩子,直接返回失败 if (targetPosition == -1) { return false; } // 直接操作原始Child对象的礼物列表,插入到末尾 auto& targetChild = this->getEntry(targetPosition); ableToInsert = targetChild.getList().insert(targetChild.getList().getLength() + 1, newEntry); return ableToInsert; }
补充小提示
- 使用引用不仅能解决你的问题,还能避免不必要的对象拷贝,提升代码性能;
- 区分
const和非const版本的方法是C++里的最佳实践,保证了const正确性——当你拿到一个const Child对象时,只能调用const方法,不会不小心修改它。
内容的提问来源于stack exchange,提问作者kirito23
相关产品推荐
相关产品推荐

