为什么成员变量不能用作参数的默认值?

时间:2012-12-03 07:03:38

标签: c++ language-lawyer default-parameters

  

可能重复:
  Nonstatic member as a default argument of a nonstatic member function

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

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

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

编辑由于答案似乎被我的问题误解了,让我澄清一下。我知道情况就是这样,而且我知道这种语言是什么和不允许的。我的问题是为什么语言设计师选择不允许这样做,因为它似乎自然有效。

4 个答案:

答案 0 :(得分:4)

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

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

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

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

所以,问题是为什么

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

是不允许的。

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

注意这个

int a;

void foo(int b = a);
在C ++中允许

。而且,显然,它没有表现出上述评估问题的顺序。

答案 1 :(得分:1)

这篇文章列出了可以设置默认参数的所有方法 - Must default function parameters be constant in C++?

解决您的需求并不困难。

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

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

给你你想要的东西。

答案 2 :(得分:1)

我认为这是标准中最合适的段落,特别是§9:

  

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

     

§7本地变量不得用于默认参数

     

§9[...]类似地,非静态成员不应在默认参数中使用,即使它未被计算,除非它显示为类成员访问表达式的id-expression(5.2。 5)或者除非它用于形成指向成员的指针(5.3.1)。

答案 3 :(得分:1)

在相关问题中总结Nawaz优秀答案:致void Foo::Bar(int a = this->member)的确是void Foo__Bar(Foo* this, int a = this->member)。显然第二个参数在第一个参数之前不能被评估,这违反了C ++公理,即编译器可以按照他们喜欢的顺序评估参数。