C++ 中 const 和 static 关键字(定义,用途)

一、static 定义及用途

static 作用: 控制变量的存储方式和可见性
1、修饰局部变量:
通常局部变量在程序中存放栈区,局部的生命周期在包含语句块执行完时便会结束,使用 static 关键字对局部变量修饰后,变量会存放静态数据区,其生命周期会延续到整个程序结束。
但是作用域没有改变,作用域还是限制在其他语句块中。
个人理解: static 修饰局部变量,可认为是 延长变量生命周期的局部变量(不会随着函数结束而是放)
2、修饰全局变量:
对于一个全局变量,它既可以在本文件中被访问到,也可以在同一个⼯程中其它源⽂件被访问(添加 extern进⾏声明即可)。⽤ static 对全局变量修饰改变了其作用域范围,由原来的整个⼯程可⻅变成了本⽂件可⻅。
3、修饰函数:
和全局变量一样 ,改变作用域,限制在本文件使用。
4、修饰类 :
对类中某函数修饰,表示该函数属于一个类,而不是此类的任何对象 ;
对类中某一个变量修饰 , 便是该变量为所有对象所有,存储空间中只有一个副本,可以通 过类和对象调用。
(补充:静态非常量数据成员,其只能在类外定义和初始化,在类内仅是声明而已。)
样例如下;

5:类成员/类函数声明
函数体内 static 变量范围为该函数体,不同于 auto 变量,该变量的内存只被分配⼀次,因此其值在下次调⽤时仍维持上次的值;
在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
在模块内的 static 函数只可被这⼀模块内的其它函数调⽤,这个函数的使⽤范围被限制在声明它的模块内;
在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
在类中的 static 成员函数属于整个类所拥有,这个函数不接收this 指针,因⽽只能访问类的static 成员变量。 static类对象必须要在类外进⾏初始化, static 修饰的变量先于对象存在,所以 static 修饰的变量要在类外初始化;
由于 static 修饰的类成员属于类,不属于对象,因此 static 类成员函数是没有 this 指针, this 指针是指向本对象的指针,正因为没有this 指针,所以 static 类成员函数不能访问⾮ static 的类成员,只能访问 static修饰的类成员;
static 成员函数不能被 virtual 修饰, static 成员不属于任何对象或实例,所以加上 virtual没有任何实际意义;静态成员函数没有 this 指针,虚函数的实现是为每⼀个对象分配⼀个 vptr 指针,⽽ vptr 是通过 this 指针调⽤的,所以不能为virtual;虚函数的调⽤关系,this->vptr->ctable->virtual function。

class Person
{
    
    
public:
	Person(string name,int age)
	{
    
    
		this->m_name = name;
		this->m_age = age;
	}
  //静态函数
   	static void func()
	{
    
    
		//m_age = 50;   静态函数只能访问静态变量
		m_score = 99;
		cout << m_score << endl;
	}
  
	string m_name;
	int m_age;
   //静态成员变量   类内声明
	static int m_score; 
};

int Person::m_score = 100; //静态变量 类外初始化

int main()
{
    
    
	Person p1("张三" , 18);
	Person p2("李四", 20);

	cout << "成绩 " << p1.m_score << endl; //通过类对象访问
	p2.m_score = 80; //静态变量 只有一个副本,一个内存空间
	cout<< "成绩 " << p2.m_score << endl; 
  
  //静态函数调用
	Person::func();    // 通过类调用
	p1.func();         //通过类对象调用
 
	return 0;
}

二、const 定义及用途

const 作用:限制可读性
1、const修饰基础数据类型
const 在基础数据类型前、后结果一样,在使用这些常量的时候不能改变常量的值。修饰符 const 可以⽤在类型说明符前,也可以用在类型说明符后,其结果是一样的。在使用这些常量的时候,只要不改变这些常量的值即可。

const int Max = 100;
int const Min = 1;

void demo()
{
    
    
	//Max = 110; 常量不可修改
	//Min = 2;   常量只读性
	cout << Max << Min << endl;
}

2、修饰指针变量和引用变量
如果const 在 * 左侧 ,则const修饰指针所指向的变量 ,即指针指向常量

如果const 在 * 右侧 ,则const修饰指针本身 ,即指针本身为常量。

int a = 10, b = 20;

//使 指针指向常量   (指针指向可改 ,指向的值不可以更改)
const int* p1 = &a;  
p1 = &b;
//*p1 = 100;              错误用法

 //使 指针本身为常量  (指针指向不可改 ,指向的值可以更改)
int* const p2 = &b; 
//p2 = &a;              错误用法
*p2 = 100;

3、const 修饰普通函数
防止传入的参数在函数体内被改变,但仅对指针、引用有意义。因为如果是按值传递,传给参数的仅仅是实参的副本,即使在函数体内改变了形参,实参也不会得到影响。如:

void func(const int i)
{
    
    
	//i = 10;  不能修改i
	cout << i << endl;
}

const修饰的函数参数是指针时,代表 在函数体内不能修改该指针所指的内容,起到保护作用:

void fun(const char * src, char * des)
{
    
      
  //保护源字符串不被修改,若修改src则编译出错。
	strcpy(des,src);
}

const 修饰函数返回值
用const来修饰返回的指针或引用,保护指针指向的内容或引用的内容不被修改。

//const 修饰函数返回值 
const int* getNum(int* a)
{
    
    
	return a;
}

int a = 10;
auto ret= getNum(&a);
//ret = 20  返回值不能修改

4、const 在类中的⽤法:
const 成员变量,只在某个对象生命周期内是常量。对于整个类而言是可以改变的。因为类可以创建多个对象,不同的对象其 const 数据成员值可以不同。所以不能在类的声明中初始化 const 数据成员,因为类的对象在没有创建时候,编译器不知道 const 数据成员的值是什么 const 数据成员的初始化只能在类的构造函数的初始化列表中进⾏。

const 成员函数:
const 成员函数的主要⽬的是防⽌成员函数修改对象的内容。要注意 const 关键字和 static 关键字对于成员函数来说是不能同时使⽤的,因为 static 关键字修饰静态成员 函数不含有 this 指针,即不能实例化 const 成员函数⼜必须具体到某⼀个函数。

常量对象:
常量对象只能调用常量函数,别的成员函数都不能调用。

补充: const 成员函数中如果实在想修改某个变量,可以使用mutable进行修饰。成员变量中如果想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现或者 static const。

class Person
{
    
    
public:
	Person(string name,int age)
	{
    
    
		this->m_name = name;
		this->m_age = age;
	}

	//常函数
	void func() const
	{
    
    
		m_sore = 100;

	}
	//普通成员函数
	void Print()
	{
    
    
		cout << "姓名: " << this->m_name << "  年纪:" << this->m_age << end;
	}
	string m_name;
	int m_age;
	mutable int m_sore =60;  //特殊变量
};

int main()
{
    
    
	const Person p("张三", 18);  // 常对象

	//常对象调用常函数
	p.func();
	//p.Print();  常对象只能调用常函数
	
	p.m_sore = 160;   //m_sore 为特殊变量只能在常对象下修改
	cout << p.m_sore << endl;

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_52302919/article/details/132319184