zhe*_*oli 4 c++ scope class typename
根据C++ Primer一节,7.4.1类型名称是特殊的:
通常,内部作用域可以从外部作用域重新定义名称,即使该名称已在内部作用域中使用过.但是,在类中,如果成员使用外部作用域中的名称并且该名称是类型,则该类可能不会随后重新定义该名称.
因此,例如:
typedef double Money;
class Account {
public:
Money balance() { return bal; }
private:
typedef double Money;
Money bal;
};
int main() {
typedef double Money;
Money asset;
typedef double Money;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当你编译上面的例子时,它会抱怨:
a.cc:6:24: error: declaration of ‘typedef double Account::Money’ [-fpermissive]
typedef double Money;
^
a.cc:1:16: error: changes meaning of ‘Money’ from ‘typedef double Money’ [-fpermissive]
typedef double Money;
Run Code Online (Sandbox Code Playgroud)
那么为什么我们不能在类中重新定义类型名称,但我们可以在内部范围内吗?
我的编译器版本是g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609.
该部分还有一个注释:
虽然重新定义类型名称是错误的,但编译器不需要诊断此错误.即使程序出错,一些编译器也会悄悄地接受这样的代码.
T.C*_*.C. 10
这不是类型所特有的.[basic.class.scope]/2:
N类中使用的名称S应在其上下文中引用相同的声明,并在完成的范围内重新评估S.违反此规则无需诊断.
原因是类范围中的名称查找有点特殊.考虑:
using Foo = int;
struct X {
Foo a; // ::Foo, i.e., int
void meow() {
Foo b = a; // X::Foo; error: no conversion from int to char*
}
using Foo = char*;
};
Run Code Online (Sandbox Code Playgroud)
成员函数体中的名称查找会考虑所有类成员,无论是在成员函数之前还是之后声明(否则,在类定义中定义的成员函数将无法使用稍后在类中声明的数据成员).结果是你得到两个Foo具有不同含义的s,即使它们都是词法上在类成员Foo的声明之前.这很容易导致极其混乱和脆弱的代码,因此标准禁止它.