C++自定义函数对象传参异常:Prog_shape类Text初始化取值为0
问题根因
你遇到的坐标取值不一致,本质是踩中了C++类成员初始化的规则盲区,和Scale的计算逻辑、图形类的绘图实现都没有关系。
C++标准明确规定:类成员的初始化顺序,完全按照类内部的成员声明先后顺序执行,和构造函数初始化列表里的书写顺序没有任何关联。
对照你写的Prog_shape的私有成员声明顺序:
- 第一行声明的是
Graph_lib::Text txt;,因此它是整个类里第一个被初始化的成员 - 第二行声明的是
Scale sc;,因此它是第二个被初始化的成员 - 第三行声明的是
Graph_lib::Circle cir;,因此它是第三个被初始化的成员
对应的构造函数实际执行流程是:
- 开始构造txt:你给txt传的初始化参数里写了
sc(p.yy)计算坐标,但此刻sc对象完全还没开始构造,它内部的cbase、vbase、scale全是未初始化的内存垃圾值,调用它的计算逻辑返回的结果毫无意义(你调试看到的0就是这类随机垃圾值的一种),所以txt拿到的坐标是错的。 - 开始构造sc:直到txt构造完,sc的默认构造函数才会运行,给cbase、vbase、scale赋上正确的固定值,sc才成为可以正常计算的函数对象。
- 开始构造cir:此刻sc已经完成正确初始化,所以这里调用
sc(p.yy)算出的坐标完全符合预期,这就是为什么cir的结果是正常的。
这就完全解释了为什么两处写了完全一样的sc调用,结果却一个错一个对。
修复方式
只需要调整成员的声明顺序,把sc移到所有要用到它的图形成员前面,保证sc最先完成初始化就行:
把类的私有成员区改成:
private: Scale sc; // 把sc移到最前面,确保它比txt、cir先初始化 Graph_lib::Text txt; Graph_lib::Circle cir;
修改后初始化流程就变成:先构造sc(所有参数值正确)→ 再构造txt(用正常的sc算坐标)→ 最后构造cir,两个图形的坐标计算就会全部正常。
- 实用提示:编译时打开
-Wreorder警告等级,编译器会在编译阶段直接检测到初始化列表顺序和成员声明顺序不匹配的问题,不用等运行时反复调试就能提前发现这类隐蔽bug。
内容的提问来源于stack exchange,提问作者c_thief
相关产品推荐
相关产品推荐

