【C++私房菜】语法中的static和const

目录

一、类内的static和const

1、类内const成员初始化

2、类内static成员初始化

3、类内static const成员初始化

二、类外的static和const

1、const

2、static

三、类内static和const的函数

1、const函数

2、static函数


在C++中,static表示是静态的。类的静态成员函数、静态成员变量都是和类相关的,而不是和类的具体对象相关的,即使没有具体对象,也能调用类的静态成员函数和成员变量。const数据成员只是某个对象生存期内的常量,而对整个类来说是可变的。类可以创建多个对象,不同的对象其const成员的值可以不同。


一、类内的static和const

1、类内const成员初始化

const成员必须在定义的时候初始化,在类中是声明。对象实例化时会按初始化列表定义。

 class yq
 {
 public:
     yq(int i = 10)
         :_i(i)
     {}
 private:
     const int _i;
 };

2、类内static成员初始化

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用 static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。(在使用时必须进行类外定义,否则报错。

static类成员不能在初始化列表初始化。static成员变量在对象生成之前生成。初始化列表是在定义初始化一个对象的成员。而static类成员变量不属于。不能给缺省值,缺省值是给初始化列表的,静态成员变量不走初始化列表。

静态成员函数和静态成员变量,本质都是受限制的全局变量和全局函数,专属所在类,受类域和访问限定符的限制。计算类的大小的时候(sizeof(类)),不算静态变量。

c++规定:static成员类内声明,类外定义。即声明和定义分离。

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。

  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。

  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。

  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。

  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。

 class Yq
 {
     Yq()
     {}
 private:
     static int _i;
 };
 int Yq::_i = 0;

静态数据成员

  • 静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。

  • 静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。

  • 静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。

  • 静态数据成员既可以通过对象名引用,也可以通过类名引用。


3、类内static const成员初始化

在C++中,static const可以用来定义一个静态常量。

其中,static关键字表示该常量只在当前文件内可见,而不会被其他文件引用;const关键字表示该变量的值是不可修改的,即它是一个常量。

使用static const可以带来以下几点好处:

  • 提高程序的效率。由于该常量是静态的,它被存储在程序的静态数据区中,只会在程序启动时被初始化一次,因此可以提高程序的运行效率。

  • 避免命名冲突。由于static关键字的存在,同名的常量不会和其他文件的同名常量发生命名冲突,从而避免了错误的发生。

  • 增加代码的可读性。由于const关键字的存在,该常量的值是不可变的,从而使得代码更加易于理解和维护。

例如,下面是一个使用static const定义静态常量的示例代码:

 // 在头文件中定义一个静态常量
 class MyClass {
 public:
     static const int MY_CONST;
 };
 ​
 // 在源文件中初始化该静态常量
 const int MyClass::MY_CONST = 100;

通过这种方式,我们可以在程序中使用MyClass::MY_CONST来访问这个常量。由于它是静态的,所以它只会被初始化一次,并且不会和其他文件的同名常量发生冲突。

二、类外的static和const

1、const

被const修饰的变量必须在定义时初始化。

应尽可能使用const

  • 使用const可以避免无意中修改数据的编程错误。

  • 使用const使函数能够处理const和非const实参,否则将只能接受非const数据。

  • 使用const引用使函数能够正确生成并使用临时变量。

2、static

  1. C++中的全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。

  2. C++中,在函数或一个代码块内部声明的变量,称为局部变量。它们只能被函数内部或者代码块内部的语句使用。当局部变量被定义时,系统不会对其初始化,必须自行对其初始化。

在程序中,局部变量和全局变量的名称可以相同。但是在函数内的局部变量与全局变量是两个独立的变量,互不影响,全局变量的值可以在局部函数内重新赋值。

c/c++内存化为三个区域:栈区、堆区、静态区

  • 栈区: 局部变量,形式参数(具有临时作用的变量)。特点:进入作用域创建,出了作用域销毁(还给操作系统)。

  • 堆区: 动态内存分配。realloc malloc calloc free

  • 静态区:全局变量静态变量。特点:创建好后,直到程序结束才销毁(还给操作系统)。

static修饰不同的变量

  1. 修饰局部变量– 称为静态局部变量 一个局部变量本来存放在栈区,但是被static修饰后存放在静态区。 static修饰局部变量改变了变量的存储类型(位置),使得该静态变量的生命周期变长,直到程序结束。

  2. 修饰全局变量– 称为全局变量 未被static修饰的全局变量具有外部链接属性,所有在其他源文件内部依然可以使用。(需要声明外部符号extern ,例:extern int val_g;)static修饰全局变量,改变了全局变量的链接属性,由外部链接属性变成了内部链接属性。这个静态变量只能在自己所在的源文件内部使用,不能在其他源文件内部使用。

  3. 修饰函数 – 称为静态函数 static修饰函数和static修饰全局变量是一样的。声明外部符号extern int Add(int x,int y); 函数具有外部链接属性,但是被static修饰,就变成了内部链接属性。使得这个函数只能在自己所在的源文件内部使用,不能在其他文件的内部使用。

三、类内static和const的函数

1、const函数

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数 隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

  • const对象可以调用const成员函数
  • const对象不能调用非const成员函数
  • 非const对象可以调用const成员函数
  • 非const对象可以调用非const成员函数
  • const成员函数不能调用非const成员函数
  • 非const成员函数可以调用非const成员函数
 void Date::Print()//此函数不能被const Date对象调用,调用时权限会扩大。
 {
     //权限可以缩小,不能扩大。
     cout << _year << "/" << _month << "/" << _day << endl;
 }
 ​
 void Date::Print() const//此函数才可以被const Date对象调用。
 {
     //权限可以缩小,不能扩大。
     cout << _year << "/" << _month << "/" << _day << endl;
 }

1、非const对象(成员函数)即可以调用const对象(成员函数),也可以调用非const对象(成员函数) 2、const对象(成员函数)只能调用const对象(成员函数),想调用非const对象(成员函数)就需要强转

const成员函数。const本质修饰*this。

成员函数定义原则:

  1. 能定义为const的成员函数都应该定义为const,这样const对象和非const对象都可以调用。

  2. 修改成员变量的函数不能定义为const

 //Date.h
 class Date
 {
     void Print() const;
 }
 ​
 //Date.cpp
 void Date::Print()const
 {
     cout << _year << "/" << _month << "/" << _day << endl;
 }
 Date* operator&()
 {
     return this;
 }
 const Date* operator&() const
 {
     return this;
 }//若没有Date* operator&(),非const对象也可以调用此函数。此函数可以不写
 //test.cpp
 void testConst()
 {
     const Date d1(2023, 10, 31);
     d1.Print();//若此函数不是const成员函数,则导致权限放大
     Date d2;
     d2.Print();
 }

类中变量分配内存在定义(Date d)时,在类中仅仅是声明。


2、static函数

static函数唯一能够访问的就是static变量或者其他static函数,且static函数属于所有对象共享,不具备this指针。但是,普通成员函数是可以调用static函数的。(补充:友元函数不具备this指针)

 class Yq {
 public:
     static int getCount()
     {
         return _count;
     }
 private:
     static int _count;
 };
 ​int Yq::_count = 1;
 int main()
 {
     cout << Yq::getCount() << Yq::getCount() << endl;
 }

静态成员函数

  • (1)静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。

  • (2)非静态成员函数有 this 指针,而静态成员函数没有 this 指针。

  • (3)静态成员函数主要用来方位静态数据成员而不能访问非静态成员。

总结:

  • (1)静态成员函数中不能调用非静态成员。

  • (2)非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。

  • (3)静态成员变量使用前必须先初始化(如 int MyClass::m_nNumber = 0;),否则会在 linker 时出错。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌岩雀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值