static数据成员 const常量 volatile关键字 详解

一.类的static成员

对于用static修饰的成员函数,称为静态成员函数;用static修饰的成员变量,称为静态成员变量.

如果对于一个成员,对其以static修饰,此时这个成员就不再属于对象(求类的大小时,不计算静态成员变量),而是属于这一整个类的所有对象.因为静态成员的生命域不在类中,而是在静态区,所以静态的成员只能在类外初始化.

特性:

  1. 静态成员为所有类对象所共享,不属于某个具体的实例
  2. 静态成员变量必须在类外初始化,初始化时不添加static关键字
  3. 类静态成员即可用类名::静态成员 或者 对象.静态成员/引用.静态成员/指针.静态成员来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员和类的普通成员一样,也有public,protected,private3种访问级别,也可以具有返回值
  6. 静态成员和全局变量虽然都存储在静态区,但是静态成员的生命周期只在本文件中,而全局变量不是

因为静态成员函数不属于某个对象,所以它没有this指针无法访问任何非静态的成员,但是非静态的成员函数具有this指针,可以访问静态的成员。

静态成员与普通成员的对比:

  1. 普通数据成员属于类的一个具体的对象,只有对象被创建了,普通数据成员才会被分配内存.而静态数据成员属于整个类,即使没有任何对象创建,类的静态数据成员变量也存在
  2. 因为类的静态数据成员的存在不依赖任何对象的存在,类的静态数据成员应该在代码中被显式的初始化,一般要在类外进行.
  3. 外部访问类的静态数据成员能直接通过类名来访问,虽然静态成员不属于类的某个对象,但是仍然可以使用类的对象,引用或者指针来访问静态数据成员
  4. 类的静态数据成员函数无法直接访问普通数据成员(可以通过对象名间接的访问),而类的任何成员函数都可以访问类的静态数据成员

类外调用静态成员的几种方式:

class A {
public:
	A() {
		cout << "构造函数" << endl;
	}
	static void num() {
		cout << "静态成员函数" << endl;
	}
	~A() {
		cout << "析构函数" << endl;
	}
};

int main() {
	A a;
	A* b = new A();
	A& a1 = a;
	//调用静态成员函数的几种方式:
	A::num(); //类名::静态成员函数
	a1.num(); //引用.静态成员函数
	a.num();  //对象.静态成员函数
	b->num(); //指针.静态成员函数
	delete b;
	return 0;
}

二.类的const成员

需要const的原因:

因为对于类和对象,封装性是一个很重要的东西,但是访问限定符只对外部有影响,对自身的成员函数没有影响,如果我们不想让一个成员函数对类的成员进行修改,这时,就需要用const来修饰成员函数。

class Date
{
public:
	//等价于 void print(const Date* this)
	void Print() const
	{
		cout << _year << '-' << _month << '-' << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	
};

对于用const修饰的成员函数,需要将const放在最后面,来区分开const参数和const返回值。这里的const其实修饰的是该成员函数的this指针,所以该成员函数就无法对类的成员进行修改

提出问题:

1.const对象可以调用非const成员函数吗?

答案:不可以,因为const对象只能读不能写(不能修改),而非const成员函数则可读可写,使

权限放大了,则不可以.

2.非const对象可以调用const成员函数吗?

答案:可以,因为非const对象可读可写(可以修改),const成员函数只可读,使权限缩小,则可以.

3.const成员函数内可以调用其它非const成员函数吗?

答案:不可以,因为const成员函数的this指针是常量,只可读,而非const的成员函数则可读可写,使权限放大了,不可以.

4.非const成员函数内可以调用其它的const成员函数吗?

答案:可以,因为非const成员函数的this指针可读可写,const成员函数只可读,使权限缩小,则可以。

三.常量指针与指针常量

常量指针:是指执行的内容是常量

const int *n;
int const *n;

注意:

  • 常量指针说的是不能通过这个指针修改变量的值,但是可以通过其他的引用来改变变量的值
int a = 5;
const int *p = &a;
a = 6; //修改成功
  • 常量指针指向的值不能改变,但是并不是意味着指针本身不能改变,常量指针可以指向其它的地址.
int a = 5;
int b = 6;
const int* n = &a;
n = &b;

指针常量:是指指针本身是个常量,不能改变指针的指向.

int* const n;
  • 指针常量指向的地址不能改变,但是地址中的数值是可以改变的

区分:常量指针和指针常量的关键在于星号的位置,以星号为分界线

  • 如果const在星号的左边,则为常量指针
  • 如果const在星号的右边,则为指针常量

指向常量的常指针:指针指向的位置不能改变且不能通过这个指针改变变量的值.(但是仍然可以通过其他的普通指针改变变量的值)

const int* const p;

 const指针和指向常量的指针几种易混淆的用法:

const int p;              int 型常量

const int *p;             p是一个指向int型常量的指针(指针指向的值不能变)

int const *p;             p是一个指向int型常量的指针(指针指向的值不能变)

int* const p;             p是一个指向int的const指针 (指针指向的地址不能变)

const int* const p;    p是一个指向int型常量的const指针(指向的值与指针指向的地址均不能变)

int const * const p;   p是一个指向int型常量的const指针(指向的值与指针指向的地址均不能变)

四.volatile关键字

volatile关键字提醒编译器所定义的变量随时有可能会改变,因此编译后的程序每次需要存储或者读取这个变量的时候,都会直接从变量地址中读取数据.如果没有volatile关键字,则编译器可能优化读取和存储,可能使用寄存器中的值.

不让编译器进行优化,到内存中读取数值,而不是在寄存器中读取数值.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值