C++类双向转换异常:ImperialSystem转SI触发static_cast报错
问题现象
跨类类型转换逻辑异常:SI 类到 ImperialSystem 类的转换可正常运行,但反向(ImperialSystem 转 SI)转换失败,报错信息为:
static_cast: cannot convert from ImperialSystem to SI
原问题代码如下:
#include<iostream> #define endl '\n' using std::cout; #define MTRTOFEETRATIO 3.28084; /* Write two classes to store distances in meter-centimeter and feet-inch systems respectively. Write conversions functions so that the program can convert objects of both types. */ class SI; class ImperialSystem { private: int mfeet; int minch; public: ImperialSystem(int m, int cm) :mfeet{ m }, minch{ cm }{}; ImperialSystem(float dis) :mfeet{ static_cast<int>(dis) }, minch{ static_cast<int>((dis - mfeet) * 12) } {} operator float() { return mfeet + minch / 12.0; } operator SI(); friend std::ostream& operator <<(std::ostream& out, const ImperialSystem& dis); }; class SI { private: int mmeter; int mcentimeter; public: SI(int m, int cm) :mmeter{ m }, mcentimeter{ cm }{}; SI(float dis) :mmeter{ static_cast<int>(dis) }, mcentimeter{ static_cast<int>((dis - mmeter) * 12) } {} operator ImperialSystem(); friend std::ostream& operator <<(std::ostream& out, const SI& dis); }; std::ostream& operator <<(std::ostream& out, const SI& dis) { out << " " << dis.mmeter << " m " << dis.mcentimeter << " cm "; return out; } std::ostream& operator <<(std::ostream& out, const ImperialSystem& dis) { out << " " << dis.mfeet << " ft " << dis.minch << " in "; return out; } ImperialSystem::operator SI() { double feet = mfeet + minch / 12; double meter = feet / MTRTOFEETRATIO; return meter; } SI::operator ImperialSystem() { double meter = mmeter + mcentimeter / 100.0; double feet = meter * MTRTOFEETRATIO; return feet; } int main() { SI s{ 20,35 }; cout << s << " = " << static_cast<ImperialSystem>(s) << endl;//this works ImperialSystem i{ 10,11 }; cout << i << " = " << static_cast<SI>(i) << endl;//but this doesnot return 0; }
错误原因
代码一共有4处问题,其中直接导致编译失败的是宏定义错误,其余是逻辑错误:
- 宏定义末尾多余分号:
#define MTRTOFEETRATIO 3.28084;末尾带了分号,宏是纯文本替换,会导致所有用到该宏的表达式被意外截断,触发类型识别错误。 - 公制单位转换系数错误:
SI类的单参数构造函数中,厘米部分计算用了英制系数*12,正确系数应为*100(1米=100厘米),会导致转换出的厘米数值完全错误。 - 整数除法精度丢失:
ImperialSystem::operator SI()中minch / 12是两个int类型运算,会触发整数除法,小于12的英寸值会被直接算为0,丢失精度,应改为浮点数除法。 - 转换运算符无const修饰:两个类型转换运算符都没有加const,无法支持const对象的转换,存在使用限制。
另外原代码中ImperialSystem的双参数构造函数参数命名用了公制的m/cm,和实际存储的英尺/英寸语义不符,容易引发后续逻辑错误。
修复后代码
#include<iostream> #define endl '\n' using std::cout; // 移除宏末尾分号,更推荐用constexpr常量替代宏 constexpr double MTR_TO_FEET_RATIO = 3.28084; class SI; class ImperialSystem { private: int mfeet; int minch; public: // 修正参数命名,匹配英尺/英寸语义 ImperialSystem(int ft, int in) :mfeet{ ft }, minch{ in }{}; ImperialSystem(double dis) :mfeet{ static_cast<int>(dis) }, minch{ static_cast<int>((dis - mfeet) * 12) } {} operator double() const { return mfeet + minch / 12.0; } operator SI() const; friend std::ostream& operator <<(std::ostream& out, const ImperialSystem& dis); }; class SI { private: int mmeter; int mcentimeter; public: SI(int m, int cm) :mmeter{ m }, mcentimeter{ cm }{}; // 修正厘米转换系数为100,参数用double避免隐式转换问题 SI(double dis) :mmeter{ static_cast<int>(dis) }, mcentimeter{ static_cast<int>((dis - mmeter) * 100) } {} operator ImperialSystem() const; friend std::ostream& operator <<(std::ostream& out, const SI& dis); }; std::ostream& operator <<(std::ostream& out, const SI& dis) { out << " " << dis.mmeter << " m " << dis.mcentimeter << " cm "; return out; } std::ostream& operator <<(std::ostream& out, const ImperialSystem& dis) { out << " " << dis.mfeet << " ft " << dis.minch << " in "; return out; } ImperialSystem::operator SI() const { // 改为浮点数除法避免精度丢失 double feet = mfeet + minch / 12.0; double meter = feet / MTR_TO_FEET_RATIO; return SI(meter); } SI::operator ImperialSystem() const { double meter = mmeter + mcentimeter / 100.0; double feet = meter * MTR_TO_FEET_RATIO; return ImperialSystem(feet); } int main() { SI s{ 20,35 }; cout << s << " = " << static_cast<ImperialSystem>(s) << endl; ImperialSystem i{ 10,11 }; cout << i << " = " << static_cast<SI>(i) << endl; return 0; }
修复后双向转换都可正常运行,转换结果精度符合预期。
内容的提问来源于stack exchange,提问作者lorem1213
相关产品推荐
相关产品推荐

