如何解决C ++:在初始化器列表中,按什么顺序更新类成员并将其传递给基类构造函数在被调用之前?
在我的代码中,有两个类:
-
Vect3
代表3D中的矢量,即x
,y
和z
-
Plane
,代表平面方程即a
,b
,c
和d
的系数
现在,Vect3
是我的基类,Plane
是派生类。
-
Vect3
类(基类):
class Vect3 {
public:
Vect3(float x,float y,float z);
Vect3(std::vector<float> vec);
void printVect3() const;
void printVect3Magnitude() const;
void printAngleWrtAxisDeg();
float rad2deg(float angle_in_rad);
protected:
float _x = 0.0;
float _y = 0.0;
float _z = 0.0;
float _magnitude = 0.0;
float _angle_wrt_X = 0.0;
float _angle_wrt_Y = 0.0;
float _angle_wrt_Z = 0.0;
void _doCalculation();
};
Vect3::Vect3(float x,float z) : _x(x),_y(y),_z(z) {
_doCalculation();
}
Vect3::Vect3(std::vector<float> vec) : _x(vec[0]),_y(vec[1]),_z(vec[2]) {
_doCalculation();
}
void Vect3::_doCalculation() {
_magnitude = sqrt(_x * _x + _y * _y + _z * _z);
_angle_wrt_X = acos(_x / _magnitude);
_angle_wrt_Y = acos(_y / _magnitude);
_angle_wrt_Z = acos(_z / _magnitude);
}
void Vect3::printVect3() const {
std::cout << "x = " << _x << " | y = " << _y << " | z = " << _z << "\n";
}
void Vect3::printVect3Magnitude() const {
std::cout << _magnitude << "\n";
}
void Vect3::printAngleWrtAxisDeg() {
std::cout << "Angle in degree,"
<< "wrt X-axis = " << rad2deg(_angle_wrt_X)
<< " | wrt Y-axis = " << rad2deg(_angle_wrt_Y)
<< " | wrt Z-axis = " << rad2deg(_angle_wrt_Z) << "\n";
}
float Vect3::rad2deg(float angle_in_rad) {
return (angle_in_rad * 180.0 / M_PI);
}
-
Plane
类(派生类):
class Plane : public Vect3 {
public:
Plane(std::vector<float> plane_coefficients);
private:
float _a = 0.0;
float _b = 0.0;
float _c = 0.0;
float _d = 0.0;
};
Plane::Plane(std::vector<float> plane_coefficients) : _a(plane_coefficients[0]),_b(plane_coefficients[1]),_c(plane_coefficients[2]),_d(plane_coefficients[3]),Vect3(_a,_b,_c) {
std::cout << "from Plane class: " << _x << " " << _y << " " << _z << "\n";
}
但是,对于以下main
,
int main() {
std::vector<float> vec1 = {1.0,1.0,1.0};
Plane plane1(vec1);
plane1.printVect3Magnitude();
plane1.printAngleWrtAxisDeg();
std::cout << "= = = = = = = = = = = =\n";
Vect3 vect3d(vec1);
vect3d.printVect3Magnitude();
vect3d.printAngleWrtAxisDeg();
return 0;
}
我的输出有些奇怪:
from Plane class: 3.07795e-41 2.8026e-45 0
0
Angle in degree,wrt X-axis = nan | wrt Y-axis = nan | wrt Z-axis = -nan
= = = = = = = = = = = =
1.73205
Angle in degree,wrt X-axis = 54.7356 | wrt Y-axis = 54.7356 | wrt Z-axis = 54.7356
在plane
构造函数中,使用初始化列表,我已经在先更新_a
,_b
和_c
,然后将它们传递给Vect3
构造函数。
因此,理想情况下,对象printVect3Magnitude()
和对象printAngleWrtAxisDeg()
的{{1}}和plane
方法的输出应该相同。
但是,基于上述输出,看来垃圾值正在传递给vect3d
构造函数!
另一方面,如果我按照以下方式修改Vect3
构造函数(即,不直接将plane
,_a
,_b
传递给_c
构造函数传递输入向量Vect3
)
plane_coefficients
然后我得到了预期的输出:
Plane::Plane(std::vector<float> plane_coefficients) : _a(plane_coefficients[0]),Vect3(plane_coefficients) {
std::cout << "from Plane class: " << _x << " " << _y << " " << _z << "\n";
}
但是为什么呢?我是否对初始化初始化列表中的类成员被更新并传递给基类构造函数(在被调用之前)的顺序感到误解?
解决方法
您是否注意到编译器警告? 无论如何在构造函数初始值设定项列表中对成员和基类进行排序,它们都将按照声明顺序进行构造,并按照相反的声明顺序进行销毁。由于基本列表是在嵌套所有成员的块之前声明的,因此在构造时,所有基本子对象都在成员之前。如果-在构造函数的初始值设定项列表中-成员和/或基址的初始值设定项未正确放置,则会生成诊断警告,但代码会编译。并且,如果将一个成员或基准初始化为在其自身之后声明的另一个基准/成员的值,则将产生UB-正如OP已经观察到的那样。
最好, FM。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。