为什么静态成员函数不能访问非静态成员?
静态数据成员和静态成员函数都属于类本身,而不是类的某个具体对象。要在类外调用公用的静态成员函数,通常使用类名加作用域运算符 ::,例如 Box::volume()。虽然也可以通过对象名调用(如 a.volume()),但这仅仅是利用了对象的类型信息,并不代表该函数真正属于对象 a。
静态成员函数的核心设计初衷是为了处理静态数据成员。它与非静态成员函数的根本区别在于:非静态成员函数拥有 this 指针,而静态成员函数没有。因为静态函数不属于任何特定对象,它不知道应该去操作哪个实例的数据,所以无法直接访问本类中的非静态成员。
如果在静态成员函数中尝试直接引用非静态成员,编译器会报错。例如:
cout << height << endl; // 若 height 是静态成员,合法
cout << width << endl; // 若 width 是非静态成员,非法
当然,如果确实需要访问非静态成员,必须显式指定对象实例,通过对象名加成员运算符 . 来实现,比如 cout << a.width << endl;。
为什么静态成员函数不能声明为 const?
将成员函数声明为 const,意味着承诺不会修改该函数所属的对象状态。从底层实现来看,后置 const 修饰符会将隐式参数 this 指针的类型从 Class* const 转换为 const Class* const,从而禁止修改成员属性(除非属性被 mutable 修饰)。
然而,静态成员函数本质上更接近于普通 C 函数,它没有 this 指针,也不绑定到任何对象实例。既然不存在'所属对象'的概念,也就无法应用 const 来约束对象状态的修改。此外,静态函数通常遵循 _cdecl 调用约定,而成员函数则是 _thiscall,这也体现了它们在底层机制上的不同。
全局变量和静态全局变量的区别
在全局变量前加上 static 关键字,就构成了静态全局变量。两者在内存存储方式上可能并无二致,但作用域截然不同。
普通全局变量的作用域贯穿整个源程序。当项目由多个源文件组成时,非静态全局变量在各个文件中都是可见且有效的,这依赖于外部链接属性。
而 static 全局变量限制了其作用域,仅在定义它的源文件内部有效。在同一项目的其他源文件中无法访问它。由于静态全局变量的作用域局限于一个翻译单元内,只能为该文件内的代码共享,因此可以有效避免在多文件项目中因同名变量引起的链接错误。
总结来说,把局部变量改为 static 改变的是生存期;而把全局变量改为 static 改变的则是作用域,限制了它的使用范围。

