全局域函数包含类时 变量作用域问题

snser 2013-11-30 02:56:30
void func()
{
const int size = 3;

class a
{
public:
int arr[size]; //1
void ff()
{
cout << size << endl; //2
}
};
}

func在全局域
请问,为什么在 1 位置数组大小可以用size,而在 2 位置输出size的时候报错,说函数无法访问size。
按我的理解,size应该对func内部都可见啊。
...全文
188 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-12-05
  • 打赏
  • 举报
回复
有关系, 如果是标准的看编译器遵守不, 如果不是标准,编译器就会按照自己的方法处理; 我用 code ::block 自带的编译器minGw; 编译一点问题也没有,可以通过的; VC6一直到VC10(VS2010)都不行。 PS: 关键是这个方法(函数)是类作用域内部的,类又位于函数作用域内部。 但从作用考虑,也是没有问题的。 至于函数作用域,因为函数内部不能定义函数,所以一般函数作用域不会重叠。 但是类内部的函数,应该怎么算作用域,单靠这个不能确定,或者有点疑问。 这就看标准了,标准没规定,或者编译器不执行标准,就只能看编译器了。
Todd_Pointer 2013-12-04
  • 打赏
  • 举报
回复
常量虽然是常量,但C++中常量与变量一样是有作用域的。 不能在一个方法中访问另一个方法的局部变/常量。所以跟编译器怎么认为无关
引用 8 楼 lm_whales 的回复:
[quote=引用 7 楼 u012908616 的回复:] 对标准了解不多, 不知道这个符合不符合标准。 但函数里的类定义在某些情况下还是有用的,比如在函数A中调用函数B,B需要一个接口指针或引用参数,可以就地搞一个内联类实现这个接口,然后构造一个实例传给B。 在Java里常用这种技术,为此Java还提供了一种简便的方法来写这种内联类。 至于楼主的问题, 为什么1可以而2不可以, 其实并不难理解, 1是在编译时使用size的值(一般编译器会把所有对常量的引用直接替换成它的值), 而2是在运行时,而且ff运行的时候不一定是在func的上下文里,这时size显然不可用。
这个如果不是标准的话,看编译器如何处理。 因为无论如何C++ 是可以识别常量 size 的; 也能够识别,函数内部定义的类和方法的。 函数内部定义的类的方法,能不能够访问函数定义的常量, 主要看实现编译器的时候,如何处理这种局部常量。 比如,认为既然类是函数内部定义的那么,常量也能够被类使用。 就像全局定义的常量那样, 那么编译器完全可以,正常编译,引用局部常量的,内部类的方法。 如果认为,对于该方法,局部常量是不可访问的。那么就会出现现在的情况。 [/quote]
ri_aje 2013-12-04
  • 打赏
  • 举报
回复
because c++11 9.8/1 states Declarations in a local class shall not odr-use (3.2) a variable with automatic storage duration from an enclosing scope. and 3.2/2 states An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied. 主楼程序中 int arr[size]; 中对于 size 的使用是 constant expression,并且 lvalue-to-rvalue conversion 立即生效,所以不属于 odr-use,因此符合标准。 而 cout << size << endl; 中的 size 不是 constant expression,所以是 odr-used,违反了 9.8/1,导致编译错误。 size 改成 static 就可以,因为 9.8/1 只规范 automatic storage duration,其实把它变成全局变量也可以绕过 9.8/1.
lm_whales 2013-12-04
  • 打赏
  • 举报
回复
这里有点小小的矛盾 1)函数内部定义的类型,作用域在函数内部 2)类的方法的作用域在类内部。 3)函数内部的非静态常量,是类的方法不可见的。 4)函数内部的静态常量,是类的方法可见的。 估计是把这种函数内部的非静态常量,视为变量处理了。
lm_whales 2013-12-04
  • 打赏
  • 举报
回复
引用 7 楼 u012908616 的回复:
对标准了解不多, 不知道这个符合不符合标准。 但函数里的类定义在某些情况下还是有用的,比如在函数A中调用函数B,B需要一个接口指针或引用参数,可以就地搞一个内联类实现这个接口,然后构造一个实例传给B。 在Java里常用这种技术,为此Java还提供了一种简便的方法来写这种内联类。 至于楼主的问题, 为什么1可以而2不可以, 其实并不难理解, 1是在编译时使用size的值(一般编译器会把所有对常量的引用直接替换成它的值), 而2是在运行时,而且ff运行的时候不一定是在func的上下文里,这时size显然不可用。
这个如果不是标准的话,看编译器如何处理。 因为无论如何C++ 是可以识别常量 size 的; 也能够识别,函数内部定义的类和方法的。 函数内部定义的类的方法,能不能够访问函数定义的常量, 主要看实现编译器的时候,如何处理这种局部常量。 比如,认为既然类是函数内部定义的那么,常量也能够被类使用。 就像全局定义的常量那样, 那么编译器完全可以,正常编译,引用局部常量的,内部类的方法。 如果认为,对于该方法,局部常量是不可访问的。那么就会出现现在的情况。
Todd_Pointer 2013-11-30
  • 打赏
  • 举报
回复
对标准了解不多, 不知道这个符合不符合标准。 但函数里的类定义在某些情况下还是有用的,比如在函数A中调用函数B,B需要一个接口指针或引用参数,可以就地搞一个内联类实现这个接口,然后构造一个实例传给B。 在Java里常用这种技术,为此Java还提供了一种简便的方法来写这种内联类。 至于楼主的问题, 为什么1可以而2不可以, 其实并不难理解, 1是在编译时使用size的值(一般编译器会把所有对常量的引用直接替换成它的值), 而2是在运行时,而且ff运行的时候不一定是在func的上下文里,这时size显然不可用。
lm_whales 2013-11-30
  • 打赏
  • 举报
回复
定义类型是为了能够到处使用。 函数内部定义的类型,只能在函数内部使用,本来就用途不大,极少使用。 类内定义方法,并使用函数内定义的常量,也不是常见的代码。 对于这种几乎用不着的代码,发生不能正确处理的情况,只是编译器的一个很小的bug。 不加修改,也不是什么大问题。 不过,你可以告知微软一下,说不定会有些一线不到的好处哦!
lm_whales 2013-11-30
  • 打赏
  • 举报
回复
引用 4 楼 snser 的回复:
static等价于将size的作用域变成外层域,也就是全局域了,这时在class的成员函数内部肯定可以访问的。 如果会把函数内部定义的类搬到函数外部,然后编译的话,int arr[size];也应该报错啊。 { const int size = 3; //以下为size的作用域 ... ... ... //以上为size的作用域 } 不是这样么? [quote=引用 1 楼 lm_whales 的回复:] VC6~VC10(VS2010) 都不行 改成 static const int size = 3; 就可以了。 估计 VC会把函数内部定义的类搬到函数外部,然后编译 这样 const int size = 3只是函数内定义的常量 类作用域内部,没有定义。 [quote=引用 楼主 snser 的回复:]
void func()
{
	const int size = 3;

	class a
	{
		public:
			int arr[size]; //1
			void ff()
			{
				cout << size << endl; //2
			}
	};
}
func在全局域 请问,为什么在 1 位置数组大小可以用size,而在 2 位置输出size的时候报错,说函数无法访问size。 按我的理解,size应该对func内部都可见啊。
[/quote][/quote] 数据定义是不会有问题的,因为 int main(){ const int size=10; struct { int a[size];//这种代码很普通,VC 一定能够正确编译这种代码。 }; return 0; } 而函数内部定义的类,并在类内部定义类的方法,本来就很少见(几乎没人这么干)。 处理不好,或者没有标准也是很正常的, 因为几乎没有人写这种代码。
snser 2013-11-30
  • 打赏
  • 举报
回复
static等价于将size的作用域变成外层域,也就是全局域了,这时在class的成员函数内部肯定可以访问的。 如果会把函数内部定义的类搬到函数外部,然后编译的话,int arr[size];也应该报错啊。 { const int size = 3; //以下为size的作用域 ... ... ... //以上为size的作用域 } 不是这样么?
引用 1 楼 lm_whales 的回复:
VC6~VC10(VS2010) 都不行 改成 static const int size = 3; 就可以了。 估计 VC会把函数内部定义的类搬到函数外部,然后编译 这样 const int size = 3只是函数内定义的常量 类作用域内部,没有定义。 [quote=引用 楼主 snser 的回复:]
void func()
{
	const int size = 3;

	class a
	{
		public:
			int arr[size]; //1
			void ff()
			{
				cout << size << endl; //2
			}
	};
}
func在全局域 请问,为什么在 1 位置数组大小可以用size,而在 2 位置输出size的时候报错,说函数无法访问size。 按我的理解,size应该对func内部都可见啊。
[/quote]
lm_whales 2013-11-30
  • 打赏
  • 举报
回复
函数内部定义类的作用不大,估计C++ 还没有来得及,把这标准化, VC会按照MS的思路,处理这种问题。
lm_whales 2013-11-30
  • 打赏
  • 举报
回复
1)处是数据定义,是没有问题的。
lm_whales 2013-11-30
  • 打赏
  • 举报
回复
VC6~VC10(VS2010) 都不行 改成 static const int size = 3; 就可以了。 估计 VC会把函数内部定义的类搬到函数外部,然后编译 这样 const int size = 3只是函数内定义的常量 类作用域内部,没有定义。
引用 楼主 snser 的回复:
void func()
{
	const int size = 3;

	class a
	{
		public:
			int arr[size]; //1
			void ff()
			{
				cout << size << endl; //2
			}
	};
}
func在全局域 请问,为什么在 1 位置数组大小可以用size,而在 2 位置输出size的时候报错,说函数无法访问size。 按我的理解,size应该对func内部都可见啊。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧