1.先说static , C++的静态变量分为静态全局变量和静态局部变量。
静态变量存放在静态代码区,是类级别的成员,优先于该类的任何对象的存在而存在,被该类的所有对象共享,所以类的静态变量要在类外初始化。
静态全局变量有全局作用域,但生命期是单个源文件,且静态全局变量必须在main()函数执行前被初始化;
静态局部变量有跟普通变量一样有局部作用域,但相比普通变量有全局生命期,即块作用域内静态局部变量创建并初始化后,下次访问此块作用域该静态变量保留上次访问遗留的值,并不会像普通变量一样在栈内重新创建变量。同时注意的是,“C++保证,函数内的局部静态对象会在该函数被调用期间,首次遇上该对象之定义式时被初始化”。在函数体内声明一个静态变量后,下次调用该函数时并不用担心重复声明的问题,因为这已被编译器做过优化,编译器的这一技术被称为“命名粉碎规则”。
当类的数据成员包含有static类型的变量时,该变量在类内声明,在类外部定义并初始化,这时该变量可以通过类名直接调用,也可以通过对象调用,但是类只有该变量的一个副本,即该类的所有对象对该变量的操作都是对同一块内存所存储的变量的操作。
而当类的成员函数中定义有static变量时,该static变量作为普通局部静态变量处理,即该变量可以在定义处初始化,有局部作用域,在函数调用结束后,不能访问该变量,但是仍然存在,在下次调用该函数时,该变量保存了上次调用结束后的值。
2.再说const ,如果const出现在*左边,表示被指物是常量(被指物内容不能修改,但指针可以指向其他对象);如果const出现在*右边,表示指针本身是常量(指针不能再指向其他对象)
1 int k = 9; 2 const int* ptr = &k; 3 const * int ptr = &k; 4 int const* ptr = &k; //以上这三种方式在vc++6.0中都是可以通过编译的,都代表变量 k的值不能被修改,但指针ptr可以指向其他对象 5 int* const ptr = &k; //这种方式代表指针ptr不能指向其他对象
一般不能给输出型参数(输出型参数就是让函数内部把数据输出到函数外部的)加const修饰,否则该参数会失去输出功能。const只能修饰输入型参数
1 int multip5_3(int a, int *p) //a=30, p=&b 2 { 3 int tmp = 5 * a; 4 *p = tmp; //此处通过输出参数在函数内部把数据输出到函数外部 5 return 0; 6 } 7 8 int main(void) 9 { 10 int a = 30, b = 0, ret = -1; 11 multip5_3(a, &b); //这里的a为输入参数,b的引用为输出参数 12 cout<<"result = "<<b<<endl; 13 return 0; 14 }
如果类中有说明一个const数据成员,那么只能通过成员初始化列表进行初始化,而不能通过构造函数。因为一旦进入构造函数,则不是初始化,而是赋值,常量变量是不允许再次赋值的。 C++提倡用const代替c的define ,将类的数据成员声明为const 即是所谓的 in-class专属常量 ,相比于define 还保证了面向对象的封装性。如果要这样使用:
1 class temp{ 2 static const int n = 5; 3 int x[n]; 4 };
必须用static保证类内至多有该变量的一份实体。而如果在普通函数内就不用static:(不在类里)
1 void t(){ 2 const int n = 5; 3 int x[n]; 4 }
在类里也可以用枚举代替 static const使用
1 class temp{ 2 // static const int n = 5; 3 // int x[n]; 4 enum { 5 n = 5 6 }; 7 int x[n]; 8 };
这是const用在类的数据成员上的一种情况,那么类的常成员函数和常对象呢 关键字const可用于区分类的重载函数,像这样的两个函数是不同的:
1 class temp{ 2 // static const int n = 5; 3 // int x[n]; 4 enum { 5 n = 5 6 }; 7 int x[n]; 8 public: 9 void g(); 10 void g() const;11 };
这是常成员函数的声明,C++ 要求声明和定义常成员函数时都需要加const。
class A{
public:
A();
};
int main(int argc, const char * argv[]) {
const A a;
return 0;
}
这里的a是常对象。 常对象的数据成员的值在对象的整个生存周期内不能被改变。在Xcode和g++中 定义常对象时,必须手动提供一个构造函数,哪怕这个构造函数什么也不做,而不能使用系统自动生成的构造函数。而在其它编译器中,如果不需要通过初始化列表对类的常数据成员初始化,则定义常对象时,不需要手动提供构造函数。https://ideone.com/tMbIAX 这个网址可以用C++14 在线编译,结论是 如果不需要通过初始化列表对类的常数据成员初始化,则定义常对象时,不需要手动提供构造函数。
那么类的常数据成员呢,常数据成员包括常量和常引用,如果类中说明了常数据成员,那么只能通过构造函数的成员初始化列表对该常数据成员初始化。
关于const在类中的使用,总结如下:
常成员函数可以访问常数据成员,也可以访问普通数据成员,但不能调用普通成员函数。
普通成员函数既可以访问普通成员变量,也可以访问常数据成员,可以调用常成员函数。
常对象只能调用他的常成员函数,常成员函数是常对象的唯一的对外接口。