在以下代码中,我为数组下标运算符提供了默认参数。
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
}
};
它工作正常。
所以,我有一个问题:
答案 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 overloading的subscripting operator中不允许使用默认参数。
除非下面明确说明,否则运算符函数不能具有默认参数。运算符函数的参数不能超过相应运算符所需的数量,如本子条款的其余部分所述。
和
operator[]
应该是一个非静态成员函数,只有一个参数。
operator()
应为具有任意数量参数的非静态成员函数。它可以有默认参数。
重载运算符尝试遵循内置运算符的相同行为;使用内置的下标运算符,始终需要(仅一个)索引,它没有默认参数。然后,不允许重载的运算符具有默认参数。另一方面,函数总是可以接受任意数量的参数并具有默认参数。
答案 2 :(得分:2)
我想你真的在问为什么标准允许一个而不是另一个。 的原因主要与人们的期望相关,而非某些技术逻辑排除了一个案例中的违约而不是另一个案例:
这是人们对[]运营商的期望。通常它意味着“获取[...]元素”,我们使用int或其他类型来对集合成员进行特定查询。我们总是对询问特定成员感兴趣,并且始终考虑到特定的查询。
现在考虑默认参数的含义。通常它意味着“你可以指定这个,但如果不是,我会假设这个默认值”。这适用于某些功能,人们已经习惯了。
改变这种情况可能会让很多人在看到{{1}}
时挠头答案 3 :(得分:1)
运算符(包括用户定义类型和内置类型的重载)旨在让人们使用从数学,逻辑和一般用法中熟悉的符号(尽管<<
和>>
看到了双重 - 作为流媒体运营商的服务,并且必须根据计算机上几乎普遍可用的有限字符进行符号折衷。转向并允许直观,熟悉的符号(如隐含的参数)的变化似乎适得其反。
operator()
是不同的,因为它在那里抽象出“调用”(通过)一个对象和调用一个硬编码函数之间的差异 - 它需要支持默认参数来正确地做到这一点。