C++通过另一类修改类对象,set方法传引用不生效如何解决?
问题根因
- C++语法明确要求:引用类型的类成员必须在构造函数的初始化列表中完成绑定,且绑定后无法重新指向其他对象
- 现有代码存在两个核心错误:
- 无参构造
Odometer():tank(tank)属于非法初始化:引用直接绑定到了自身未初始化的成员变量,本质是野引用,运行必然出现未定义行为 setOdoIndex中的this->tank = tank并没有修改引用的绑定关系,只是将传入对象的内容赋值给引用原本绑定的对象,完全达不到更换关联油量表的需求
- 无参构造
解决方案
如果需要支持「先实例化Odometer、后关联FuelGauge对象」的延迟绑定场景,最稳妥的方案是将引用成员替换为指针成员,既保留修改外部油量表的能力,又符合语法规则。
修改后完整可运行代码
#include <iostream> using namespace std; class FuelGauge { protected: double galls; double check(double) const; public: FuelGauge(double galls){ check(galls); this->galls = galls; } FuelGauge(){ *this = FuelGauge(0); } double getFuelLeft() const{ return galls; } FuelGauge operator++(){ if (galls >= 15) throw "Tank max capacity is 15 gallon"; ++galls; return *this; } FuelGauge operator--(){ if (galls == 0) throw "Tank is empty"; --galls; return *this; } void refuel(){ galls = 15; } }; double FuelGauge::check(double n) const { if (n < 0) throw "Dont accepted negative value!"; if (n > 15) throw "Tank max capacity is 15 gallon"; return n; } class Odometer{ private: int odo; // 替换为指针成员,支持延迟绑定 FuelGauge *tank = nullptr; void calOdo() { if (odo > 999999) {odo = 0;}; } public: Odometer(int odo, FuelGauge &tank):tank(&tank) { this->odo = odo; } // 无参构造默认tank为空指针 Odometer() { odo = 0; } int getOdoIndex() const{ return odo; } void setOdoIndex(int odo, FuelGauge &tank) { this->odo = odo; // 直接修改指针指向,实现更换关联油量表 this->tank = &tank; } void carDrive() { // 调用前判空,避免空指针异常 if (!tank) throw "Odometer not bind FuelGauge yet"; --(*tank); calOdo(); ++odo; } }; int main() { FuelGauge tank; cout << "--Fill the tank--" << endl; try { for (int i = 0; i < 15; i++) { ++tank; } } catch(const char* e) { cerr << e << '\n'; } cout << "\n--Car run (先实例化Odometer后关联油量表场景)--" << endl; // 先实例化空的Odometer对象 Odometer odo1; // 再通过set方法关联油量表 odo1.setOdoIndex(0, tank); try { for(int i = 0; i < 16; i++) { cout << "Index of odometer: " << odo1.getOdoIndex() << endl; cout << "Fuel left: " << tank.getFuelLeft() << endl; odo1.carDrive(); } } catch(const char* e) { cerr << e << '\n'; } return 0; }
核心修改说明
- 将
Odometer类的成员FuelGauge &tank改为FuelGauge *tank,默认初始化为空指针 - 所有构造函数、
setOdoIndex方法依然保留传入FuelGauge&的接口,仅在内部将地址赋值给指针,不改变外部调用习惯 - 调用油量表方法前增加空指针判断,避免未绑定对象时运行异常
内容的提问来源于stack exchange,提问作者huy luong
相关产品推荐
相关产品推荐

