const 与 static
static
对普通变量和函数
- 变量
在变量前加上关键字,被定义为一个全局静态变量或者局部静态变量。
在内存中的位置:静态存储区(程序运行期间一直存在)。
初始化:未被显示初始化的全局或者局部静态变量会被程序自动初始化为0。
作用域:全局静态变量的作用域在声明他的文件内可见;局部静态变量的作用域在它的函数或者语句块结束的时候,随之结束。
- 函数
在返回值类型前加上关键字,就被定义为全局静态函数。只在声明它的文件中可见。
作用:
- 不会被其他的文件修改、访问。
- 其他文件可以定义相同名字的函数,不会发生冲突。
对成员变量和函数
- 成员变量
成为类的全局变量,会被类的所有对象共享,包括派生类的对象。
初始化必须在类外进行初始化(初始化的格式为 int base::var = 10),而不能在构造函数内初始化。因为静态成员变量是属于类的不是对象的,如果在类中初始化所有类的对象都会包含,这是矛盾的。且在类外定义不用加stastic
修饰。
作用:为多个对象共享数据。
存储位置:和普通静态变量一样,都存储在静态存储区。到程序结束后释放。
作用域:静态成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。 然而,普通成员变量则随着对象的创建而创建,销毁随之释放。
- 成员函数
静态成员函数,使函数仅此一份,其他类对象共享此函数,不含this指针。这导致:1. 不能直接存取类的非静态成员变量,调用非静态成员函数。2. 不能被声明为virtual。
静态成员函数可以独立访问,无需创建任何对象实例就可以访问。base::func(5,3)
因为静态成员函数不含this指针,非静态成员函数在调用时 this指针被当作参数传进。
而静态成员函数是属于类,不属于对象,没有 this 指针
【或者可以这样理解:类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。】。
作用:不在于数据共享,而是管理静态数据成员,完成对静态数据成员的封装。
const
- 修饰变量:变量的值不可修改,为只读常量。
- 修饰指针:
const char* p :表示指向的内容不能被改变;
char* const p : 表示指向的地址不能改变,内容可以改变。 - 修饰函数参数
- 修饰函数返回值
- 修饰成员变量:
不能在类定义处初始化,只能通过构造函数初始化列表初始化,必须有构造函数。
class base
{
public:
base():i(100){}
private:
const int i=100;//error!!!
};
//通过这样的方式来进行初始化
base::base():i(100)
{}
- 修饰成员函数:
默认有const *this
指针。- 该函数不能改变对象的成员变量
- 不能调用非const成员函数
- const类对象只能调用const成员函数
- const数据成员只在某个对象的生存周期内是常量,但对整个类而言是可变的。因为类可以创建多个对象,每一个对象的const数据成员的值是不同的。因此不能在类声明时初始化,因为在没有创建对象之前,编译器不知道数据成员的值是什么。
const 与 #define 的区别
- 编译器处理方式不同
define --> 在预处理阶段进行替换
const --> 在编译阶段确定其值
- 类型检查
define --> 无类型,不进行类型安全检查,可能会产生错误
const --> 有数据类型,编译时会检查
- 内存空间
define --> 不分配内存,给出的是立即数,用了多少次就进行多少次替换,在内存中会有多个拷贝,消耗内存大
const --> 在静态存储区分配空间,程序运行中在内存中只有一次拷贝
- 在编译时,编译器通常不为const分配空间而是保存在符号表中,使得成为编译期间的常量,没有存储与读内存的操作,效率高。
- 宏替换只做替换,不做表达式计算。