为下标运算符和函数调用运算符提供默认参数

时间:2017-11-15 12:35:21

标签: c++ operator-overloading operators language-lawyer default-arguments

在以下代码中,我为数组下标运算符提供了默认参数

struct st 
{
    int operator[](int x = 0)
    {
        // code here
    }
};

但是,编译器生成了一个错误:

error: 'int st::operator[](int)' cannot have default arguments
     int operator[](int x = 0)

但是,如果我为函数调用运算符提供默认参数。

struct st 
{
    int operator()(int x = 0)
    {
        // code here
    }
};

它工作正常。

所以,我有一个问题:

  • 为什么不允许数组下标运算符的默认参数?
  • 为什么允许函数调用操作符的默认参数?

4 个答案:

答案 0 :(得分:13)

  
      
  • 为什么不允许数组下标运算符的默认参数?
  •   
  • 为什么允许函数调用运算符的默认参数?
  •   

主要是因为C ++语法这么说。根据A.4 [gram.expr]:

postfix-expression --> postfix-expression [ expr-or-braced-init-list ] 
                   --> postfix-expression ( expression-list opt ) 
                   --> simple-type-specifier (expression-list opt) 
                   --> typename-specifier ( expression-list opt )

大括号的参数是可选的,括号的参数不是。 正如评论中所建议的那样,请注意括号需要精确一个参数,而大括号可以采用任意数量的参数。

还要考虑一下宋玉瑶对标准明确声明的回答。

答案 1 :(得分:13)

该标准非常明确地说明了这一点。

operator overloadingsubscripting operator中不允许使用默认参数。

  

除非下面明确说明,否则运算符函数不能具有默认参数。运算符函数的参数不能超过相应运算符所需的数量,如本子条款的其余部分所述。

  

operator[]应该是一个非静态成员函数,只有一个参数。

适用于function call operator

  

operator()应为具有任意数量参数的非静态成员函数。它可以有默认参数。

重载运算符尝试遵循内置运算符的相同行为;使用内置的下标运算符,始终需要(仅一个)索引,它没有默认参数。然后,不允许重载的运算符具有默认参数。另一方面,函数总是可以接受任意数量的参数并具有默认参数。

答案 2 :(得分:2)

我想你真的在问为什么标准允许一个而不是另一个。 的原因主要与人们的期望相关,而非某些技术逻辑排除了一个案例中的违约而不是另一个案例:

这是人们对[]运营商的期望。通常它意味着“获取[...]元素”,我们使用int或其他类型来对集合成员进行特定查询。我们总是对询问特定成员感兴趣,并且始终考虑到特定的查询。

现在考虑默认参数的含义。通常它意味着“你可以指定这个,但如果不是,我会假设这个默认值”。这适用于某些功能,人们已经习惯了。

改变这种情况可能会让很多人在看到{{1}}

时挠头

答案 3 :(得分:1)

运算符(包括用户定义类型和内置类型的重载)旨在让人们使用从数学,逻辑和一般用法中熟悉的符号(尽管<<>>看到了双重 - 作为流媒体运营商的服务,并且必须根据计算机上几乎普遍可用的有限字符进行符号折衷。转向并允许直观,熟悉的符号(如隐含的参数)的变化似乎适得其反。

operator()是不同的,因为它在那里抽象出“调用”(通过)一个对象和调用一个硬编码函数之间的差异 - 它需要支持默认参数来正确地做到这一点。