C ++中的函数默认参数

时间:2013-03-04 08:22:25

标签: c++ default-parameters

我在求职面试中被问过这个问题,即使在编写之后,我仍然不理解结果......

我有以下课程:

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

现在,为什么会这样?

5 个答案:

答案 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)。和 逗号是逗号运算符(不是逗号标点符号), 它评估左手的参数,然后是右手 争论的结果,右手的结果 论点。 (左手参数的结果被抛出 离开。)