[英]Function Default Parameters in C++
我在求职面试中被问到这个问题,即使在编写之后,我仍然不明白结果......
我有以下课程:
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
现在,为什么呢?
由于逗号运算符和非显式构造函数。 表达式(a + r * xCoord , a + r * yCoord)
是逗号运算符的应用程序,其值为a + r * yCoord
,现在Point
构造函数的单参数隐式形式与此值一起使用,第二个参数是默认的。
您可以通过使构造函数explicit
来防止此类错误进入,这通常建议用于可以使用一个参数调用的任何构造函数,除非您确实需要隐式转换。
要获得所需的行为,您需要直接初始化:
Point p(a + r * xCoord, a + r * yCoord);
这是一个棘手的问题......表达
(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 ++可以隐式地使用它们进行转换,有时候会以令人惊讶的方式使用它们。
最后一点是,奇怪的是代码中使用的逗号运算符没有产生警告,因为第一个表达式没有副作用,编译器应该能够检测到这可能是一个错误。
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);
你可能想要改变
Point p = (a+r*xCoord , a+r*yCoord);
成
Point p (a+r*xCoord , a+r*yCoord);
前者使用逗号运算符为您提供一个值(您在逗号运算符表达式中的最后一个值),然后将其分配给您的对象,这将设置您的x
成员并将您的y
成员默认为零。
后者将使用两个参数调用构造函数。
这是因为您正在使用转换运算符,是Point
double
。 当使用拷贝初始化(初始化用=
符号),则表达式到的右侧=
首先被转换到该类型的左侧,然后拷贝构造被使用(在概念上,至少)。 使用复制初始化无法指定多个参数。 所以右边的表达式是(a + r*xCoord, a + r*yCoord)
。 逗号是逗号运算符 (不是逗号标点符号),它用于评估其左手参数,然后是右手参数,并为结果提供右手参数的结果。 (并且左手参数的结果被丢弃了。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.