C++98中StorageConnection对象无法填充Controller向量问题
问题排查:嵌套类vector容器数据无法存入的原因及解决办法
问题描述
我创建了多层嵌套类,每个类都包含对应对象的vector容器。尝试把已填充数据的vector<Controller>添加到StorageConnection对象时,发现对象里没存入任何Controller数据。确认添加前controllerListTemp有有效数据,但执行复制后,storageConnectionTemp.getFileSystem(0).getControllerListSize()一直返回0。项目基于C++98开发,不能用新版本特性。
相关类定义代码
class Host { public: Host () : hostName_("") { } // setters and getters for hostName_ private: string hostName_; }; class Controller { public: Controller() : controllerName_(""), hostList_() { } int getHostListSize() {...} Host getHost( int index ) { return hostList_.at(index); } Host getHost( string hostName ) {...} vector<Host> getHostList() { return hostList_;} void addToHostList(Host host) { hostList_.push_back(host); } void clearHostList() { hostList_.clear(); } // setters and getters for controllerName_ private: string controllerName_; vector<Host> hostList_; }; class FileSystem { public: FileSystem() : fileSystemName_(""), controllerList_() { } int getControllerListSize() {...} Controller getController( int index ) { return controllerList_.at(index); } Controller getController( string controllerName ) {...} vector<Controller> getControllerList() { return controllerList_;} void addToControllerList(Controller controller) { controllerList_.push_back(controller); } void clearControllerList() { controllerList_.clear(); } // setters and getters for fileSystemName_ private: string fileSystemName_; vector<Controller> controllerList_; }; class StorageConnection { public: StorageConnection() : siteName_(""), fileSystemList_() { } int getFileSystemListSize() {...} FileSystem getFileSystem ( int index ) { return fileSystemList_.at(index); } FileSystem getFileSystem ( string fileSystemName) {...} vector<FileSystem> getFileSystemList() { return fileSystemList_;} void addToFileSystemList(FileSystem fileSystem) { fileSystemList_.push_back(fileSystem); } void clearFileSystemList() { fileSystemList_.clear(); } // setters and getters for siteName_ private: string siteName_; vector<FileSystem> fileSystemList_; };
填充方法代码
void populateStorageConnection() { vector<Controller> controllerListTemp; StorageConnection storageConnectionTemp; // 已完成controllerListTemp和storageConnectionTemp中fileSystemList的填充 // 将controllerList添加至storageConnectionTemp对象 for ( int controllerCounter = 0; controllerCounter < controllerListTemp.size(); controllerCounter++ ) { storageConnectionTemp.getFileSystem(0).addToControllerList(controllerListTemp.at(controllerCounter)); } }
问题原因
核心问题在于所有getter方法返回的是对象副本,而非原容器内对象的引用:
StorageConnection::getFileSystem(int)返回的是FileSystem对象的副本,不是fileSystemList_容器里的原对象- 调用
storageConnectionTemp.getFileSystem(0).addToControllerList(...)时,实际是在临时副本上添加数据,副本执行完代码后就被销毁,原storageConnectionTemp内的FileSystem对象完全没被修改 - 同理,其他类如
Controller的getter方法也存在返回副本的问题,但本次直接触发问题的是getFileSystem的返回值特性
解决办法
方法1:新增返回引用的getter方法
修改类定义,添加返回非const引用的getter(用于修改原对象),同时保留原有的返回副本的getter(用于只读场景):
class StorageConnection { public: // 新增:返回引用,用于修改原对象 FileSystem& getFileSystemRef(int index) { return fileSystemList_.at(index); } FileSystem& getFileSystemRef(string fileSystemName) { /* 实现逻辑:找到对应对象并返回引用 */ } // 原有只读getter保留 FileSystem getFileSystem(int index) { return fileSystemList_.at(index); } // ... 其他原有代码 }; class FileSystem { public: // 同理新增返回引用的getter Controller& getControllerRef(int index) { return controllerList_.at(index); } Controller& getControllerRef(string controllerName) { /* 实现逻辑 */ } // ... 其他原有代码 };
修改填充代码,使用引用getter操作原对象:
for (int controllerCounter = 0; controllerCounter < controllerListTemp.size(); controllerCounter++) { storageConnectionTemp.getFileSystemRef(0).addToControllerList(controllerListTemp.at(controllerCounter)); }
方法2:添加批量操作的成员函数
在FileSystem类中添加直接接收vector<Controller>的批量添加方法,同时在StorageConnection中封装直接操作指定FileSystem的接口,避免通过getter接触对象:
class FileSystem { public: void addAllToControllerList(const vector<Controller>& controllers) { for (size_t i = 0; i < controllers.size(); ++i) { controllerList_.push_back(controllers[i]); } } // ... 其他原有代码 }; class StorageConnection { public: void addAllControllersToFileSystem(int fsIndex, const vector<Controller>& controllers) { fileSystemList_.at(fsIndex).addAllToControllerList(controllers); } // ... 其他原有代码 };
填充代码简化为:
storageConnectionTemp.addAllControllersToFileSystem(0, controllerListTemp);
补充说明
如果仅需读取数据,原有的返回副本的getter完全可用;但如果要修改容器内的对象,必须使用返回引用的getter或直接封装操作接口,否则所有修改都只会作用在临时副本上,原数据不会有任何变化。
内容的提问来源于stack exchange,提问作者Llama
相关产品推荐
相关产品推荐

