1. const
- 常量变量
const 类型说明符 变量名
const int num = 1; // 在定义num后,不能对该变量进行修改
- 常引用
const 类型说明符 &引用名
const int &num = a;
num = 1; //错误
a = 1; // 正确
/* 注意:
在什么时候使用常引用:如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在
函数中被改变,就应使用常引用
*/
- 常对象
类名 const 对象名 或者 const 类名 对象名
class A
{
private:
int a;
public:
A(int b){a = b;}
};
A const A_num(5);
// const A A_num(5); 和上面的那个常对象是等价的
/*
注意:
1. 在定义常对象的时候,必须要有初值
2. 如果定义常对象,则不能调用该对象中非const成员函数(系统隐式调用的构造函数和
析构函数)
3. 增加数据的安全性,防止误操作而改变相关数据
4. 常对象的成员数据都是常成员数据,因此常对象的构造函数只能用参数初始化表对常数
据成员进行初始化。*/
- 常成员数据
const 数据类型 常量名
class A
{
private:
const int num;
// 常成员数据赋初值
A(int num1){num = num1;} //错误
A(int num1):num(num1){} //正确
/*常成员数据的作用和用法与普通常量变量相似,用关键字const来声明常数据成员。常数据
成员的值是不能改变的。*/
};
- 常成员函数
类名::fun(形参) const
class A
{
private:
int num_a;
int num_b;
int sum;
public:
A(int a = 5, int b = 6){num_a = a; num_b = b;sum = 0;}
void sum_num() const;
}
A::void sum_num() const
{
sum = sum_a + sum_b;
}
/*注意:
1. const是函数类型的一部分,在声明函数和定义函数时都要有const关键字,
在调用时不必加const;
2. 常成员函数可以引用const数据成员,也可以引用非const的数据成员。
const数据成员可以被const成员函数引用,也可以被非const的成员函数引用。
*/
- 常数组
类型说明符 const 数组名[大小]
int const arr[10];
- 常指针
const 类型说明符 指针名* 或者 类型说明符 const 指针名*
const int *p;
int const *p;
[ const使用场景 ]
const修饰普通变量(例如:全局、局部变量);
const修饰函数形参,一般和引用同时使用;
const修饰函数返回值;
const修饰类数据成员,必须在构造函数的初始化列表中初始化;
const修饰类成员函数,实际修饰隐含的this,表示在类中不可以对类的任何成员进行修改;
在const修饰的成员函数中要对类的某个数据成员进行修改,该数据成员定义声明是必须加mutable关键字。
const修饰this指针不能改变
const对象可以调用非const成员函数和const成员函数吗?
不能,调用非const成员函数(如果调用非const则与const相矛盾);
可以,调用const成员函数。
非const对象可以调用非const成员函数和const成员函数吗?
都可以调用。
const成员函数内可以调用其它的const成员函数和非const成员函数吗?
不能,调用其它的非const成员函数;
可以,调用其它的const成员函数。
非const成员函数内可以调用其它的const成员函数和非const成员函数吗?
都可以调用。
2. static
static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。
static在C和C++中的区别:
C语言:
1。变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别;
2.变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
C++:
1、静态成员为所有类对象所共享,不属于某个具体的实例;
2、类静态成员即可用类名::静态成员或者对象.静态成员来访问;
3、类静态成员变量必须在类外定义,定义时不添加static关键字;
4、类的静态成员函数没有默认的this指针,因此在它里面不能使用任何非静态成员。
5、静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值,const修饰符等参数。
注意:
A.若全局变量仅在单个文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;
D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)
E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。
C++静态成员函数问题:
1.静态成员函数可以调用非静态成员函数吗?
不能;静态成员函数没有this指针,是所有类对象公有的。成员函数有this指针,每个对象都有自己独立的一份。在调用成员函数时,实际上是this->成员函数。一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错。
2.非静态成员函数可以调用类的静态成员函数吗?
可以;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。
3. extern
在C语言,用extern修饰符修饰的变量或者函数,表示“此变量或者函数在其它文件已经定义,在这里只做引用处理”。
// file.cpp
int num = 100;
// file2.cpp
#include <iostream>
using namespace std;
extern int num;
int main()
{
cout << "num = " << num << endl;
return 0;
}
编译时,将file.cpp 和 file2.cpp一起编译,其运行如下:
g++ file.cpp file2.cpp -o file //编译
./file // 运行执行文件
num = 100
注意:
extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。
// file3.cpp
#include <iostream>
using namespace std;
int sum_num()
{
int sum = 0, b = 2;
sum = num + b;
}
编译时,其运行如下:
g++ file.cpp file2.cpp file3.cpp -o file //编译
// 出现错误提示,编译不过去
// 在file3.cpp中num为定义