我在求职面试中被问过这个问题,即使在编写之后,我仍然不理解结果......
我有以下课程:
class Point
{
public:
Point(double x = 0, double y = 0) { m_X = x; m_Y = y; }
double m_X, m_Y;
};
和main.cpp是:
int main()
{
double a = 1, r = 1, xCoord = 5, yCoord = 7;
Point p = (a+r*xCoord , a+r*yCoord);
cout<<"X = "<<p.m_X<<" Y = "<<p.m_Y<<endl;
return 0;
}
p类的数据成员获取值:
m_X = a+r*yCoord, m_Y = 0
现在,为什么会这样?
答案 0 :(得分:4)
由于逗号运算符和非显式构造函数。表达式(a + r * xCoord , a + r * yCoord)
是逗号运算符的应用程序,其值为a + r * yCoord
,现在Point
构造函数的单参数隐式形式与此值一起使用,第二个参数是默认的。
您可以通过创建构造函数explicit
来防止此类错误进入,这通常建议用于可以使用一个参数调用的任何构造函数,除非您真的需要隐式转换。
要获得所需的行为,您需要直接初始化:
Point p(a + r * xCoord, a + r * yCoord);
答案 1 :(得分:2)
这是一个棘手的问题......表达式
(a+r*xCoord , a+r*yCoord)
是comma operator
表达式,因此您的代码实际上是
Point p = a+r*yCoord;
构造函数可以用作转换构造函数(因为它不是explicit
),因此它与写入相同:
Point p(a+r*yCoord, 0);
要获得“预期结果”,您应该删除等号并写入
Point p(a+r*xCoord , a+r*yCoord);
一般来说,最好使用两个不同的构造函数,而不是依赖于默认参数,例如:
struct P2d {
double x, y;
P2d() : x(0), y(0) { }
P2d(double x, double y) : x(x), y(y) { }
};
你应该总是特别注意只带一个参数的构造函数(或者你只能传递一个参数,比如你的例子),因为除非它们被声明explicit
C ++可以隐式使用它们进行转换,有时以令人惊讶的方式。
最后一句话是奇怪的是,代码中使用的逗号运算符没有产生警告,因为第一个表达式没有副作用,编译器应该能够检测到这可能是一个错误。
答案 2 :(得分:1)
Point p = (a+r*xCoord , a+r*yCoord);
(表达式)使用comma operator
,它会按顺序评估所有术语 ,返回最右边。
正确的表格将是
auto p = Point(a+r*xCoord , a+r*yCoord);
Point p(a+r*xCoord , a+r*yCoord);
答案 3 :(得分:1)
您可能想要更改
Point p = (a+r*xCoord , a+r*yCoord);
到
Point p (a+r*xCoord , a+r*yCoord);
前者使用逗号运算符为您提供一个值(逗号运算符表达式中的最后一个),然后将其分配给对象,这将设置x
成员,并将您的y
成员默认为零。
后者将使用两个参数调用构造函数。
答案 4 :(得分:1)
这是因为您正在使用转化运算符double
Point
。当您使用复制初始化(初始化时使用
一个=
符号),=
右边的表达式是第一个
转换为左侧的类型,然后是复制构造函数
(概念上,至少)使用。没有办法指明
使用复制初始化的多个参数。所以你的
右边的表达式为(a + r*xCoord, a + r*yCoord)
。和
逗号是逗号运算符(不是逗号标点符号),
它评估左手的参数,然后是右手
争论的结果,右手的结果
论点。 (左手参数的结果被抛出
离开。)