6

可能重复:
非静态成员作为非静态成员函数的默认参数

如果我错了,请纠正我,但我认为默认参数的工作方式是这样的:

当编译器看到函数调用时,它开始将参数压入堆栈。当它用完参数时,它将开始将默认值压入堆栈,直到所有必需的参数都被填充(我知道这是一种简化,因为参数实际上是从右向左压入的,所以它将以默认值开始,但是想法是一样的)。

如果这是真的,为什么不能将成员变量用作默认值?在我看来,由于编译器像往常一样在调用站点推送它们,它应该能够很好地解决它们!

编辑由于答案似乎我的问题被误解了,让我澄清一下。我知道情况就是这样,我知道该语言允许什么和不允许什么。我的问题是为什么语言设计者选择不允许这样做,因为它似乎很自然地起作用。

4

4 回答 4

4

你所问的本质可以提炼成这个简单的例子

void foo(int a, int b = a);

这在 C++ 中是不允许的。C++ 不允许默认参数依赖于其他参数。

使用类成员作为默认参数只是上述情况的一个特例,因为类成员是通过this指针访问的,而this指针只是每个非静态成员函数的另一个隐藏参数。

所以,问题是为什么

void foo(int a, int b = a);

不允许。

不允许这样做的一个明显的潜在原因是它会对参数评估的顺序施加额外的要求。如您所知,在 C++ 中,函数参数求值的顺序是未指定的——编译器可以按任何顺序求值。但是,为了支持上述默认参数功能,编译器必须确保ab. 这感觉像是一个过度的要求,它限制了我们习惯于在 C++ 中看到的典型的评估顺序自由。

请注意,这

int a;

void foo(int b = a);

在 C++ 中是允许的。而且,显然,它没有表现出上述的评估顺序问题。

于 2012-12-03T09:03:05.343 回答
1

这篇文章列出了可以设置默认参数的所有方式 -默认函数参数必须在 C++ 中保持不变吗?

解决您的需求并不难。

class A
{
    int a;
    public:
    void f(int i);

    void f()
    {
        f(a);
    }
};

给你你想要的。

于 2012-12-03T07:09:54.820 回答
1

我相信这是标准中最合适的段落,尤其是§9:

8.3.6 默认参数 [dcl.fct.default]

§7 局部变量不得用于默认参数

§9 [...] 类似地,非静态成员不得在默认参数中使用,即使它没有被评估,除非它作为类成员访问表达式 (5.2.5) 的 id 表达式出现或除非它用于形成指向成员的指针(5.3.1)。

于 2012-12-03T07:12:40.767 回答
1

总结 Nawaz 在链接问题中的出色答案:调用void Foo::Bar(int a = this->member)真的意味着void Foo__Bar(Foo* this, int a = this->member)。显然,第二个参数不能在第一个参数之前计算,这违反了 C++ 公理,即编译器可以按照他们喜欢的任何顺序计算参数。

于 2012-12-03T08:54:47.987 回答