C++中静态成员函数与静态成员变量(static )

作者:lqh 时间:2021-11-08 07:31:38 

C++中静态成员函数与静态成员变量(static )

这篇介绍了静态成员函数与静态成员变量,是我的读书笔记,我希望它够简短但又比较全面,起到复习的作用。如果有一些C++知识记不清楚了,它可以帮你很快回忆起来。

复习C语言的static关键字

(1)加在局部变量的前面使之成为静态局部变量,作用域还是在函数内部,可是生存周期延长了。

(2)加在全局变量的前面限定该变量作用域为文件作用域,就是说即使其他文件使用了extern扩展作用域也不行。这在C语言的多人项目中非常有用,避免了变量的重名。然而在C++中这一功能已经被命名空间取代,但是为了保持和C语言的兼容,static还是有这样的功能。

(3)加在函数定义或声明的前面,限定函数作用域到文件作用域,也是为了避免多个文件中有重名函数。

当static关键字出现在类中

当static出现在类的定义中便出现了静态成员变量和静态成员函数。静态成员是属于类的,而不是属于某个对象的。即便没有任何一个实例,类的静态成员变量也已经存在了,而且还可能通过“类名::成员名”进行访问。类的静态成员函数也可以用相同的方式调用,在类产生实例之前就调用成员方法,典型应用是实现单例模式。

(1)静态成员变量

静态成员变量本质上是全局变量,但是将和某些类关系紧密的全局变量写到类里面,形式上成为一个整体,更容易理解和维护。所以尽量使用静态成员变量吧,减少全局变量的使用。普通成员变量每个对象都有各自的一份,但是静态成员变量一共只有一份,被所有的本类对象共享。如果使用sizeof运算符计算对象的大小,得到的结果是不包含静态成员变量在内的。

静态成员同样受到private,public等的限制。

静态成员变量的一个典型应用就是用来计数生成的实例的个数。大体思路是设置一个名为num的静态成员变量并初始化为0,在构造函数中++num,析构函数中--num。这样num的值就是当前实例的个数。实际上这也带来了一个隐蔽的bug。看下面的代码:


class CNum {
  public:
      static int num;
      ~CNum() { --num; }
      CNum() { ++num; }
};

int CNum::num = 0;
void fun(CNum n){ }

int main() {
  CNum n;
  fun(n);
  fun(n);
  cout << CNum::num << endl;
 return 0;
}

结果:-1

num尽然成了一个负数,难道析构函数比构造函数多调用了一次?实际上不是的。当执行 fun(n); 语句时调用了复制构造函数,这个函数因为我们没有给出实现,所以是用的编译器默认提供的版本,在这个构造函数中并没有++num这条语句,因此少计数了两次(两次调用fun(n))。

解决的方法就是一定要提供自己写的复制构造函数并在函数体中加入 ++num;

(2)静态成员函数

静态成员函数内部不能调用非静态成员函数,原因是,非静态成员函数需要传入一个this指针,这让静态成员函数很为难,它并不知道与之相关的信息,也就无法提供this指针。

静态成员变量的初始化

上面代码中的第8行  int CNum::num = 0; 是静态成员变量的初始化。这可以视为是静态变量的定义(定义的同时初始化,即便不初始化也需要这个定义),而把类内的 static int num; 视为一个声明,这样的理解可以突出这样一个事实:静态成员变量本质上是全局变量。注意在类外定义时加上“类名::”。

对于常量成员变量,我们知道初始化时一定要使用初始化列表,那么当一个变量既是常量又是静态成员时(同时被const和static修饰)要怎么样初始化呢?是像一般的静态成员变量一样在类外定义并初始化,还是像一般的常量成员变量一样使用初始化列表呢?答案时前者,即在类外定义并初始化,在类内声明,就像下面那样:


class CNum {
  public:
     const static int num;
};

const int CNum::num = 0;

int main() {
  CNum n;
 return 0;
}

实际上,完全可以把const int 视为一种数据类型,它的地位和int一样。这样理解是有好处的,比如从const int到int需要强制类型转换,把他们看成两种类型,这就自然而然。相应的const char 和char 也应该看成两种类型,就好像它们完全没有什么特殊的关系一样。

另外static const int类型和static const char 类型可以在类内直接初始化,就是说都不需要在类外再次定义,像下面这样:


class CNum {
  public:
    const static int a = 19;
};

int main() { 8   cout << CNum::a << endl;//输出19
 return 0;
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

来源:http://www.cnblogs.com/painterQ/p/7009404.html

标签:C++,静态函数,静态变量,static
0
投稿

猜你喜欢

  • Flutter使用sqflite处理数据表变更的方法详解

    2023-10-21 11:05:49
  • 解决SpringMVC使用@RequestBody注解报400错误的问题

    2022-02-26 16:06:43
  • MyBatis-plus实现逆向生成器

    2021-08-26 16:37:14
  • Android中设置组件半透明和透明的效果示例

    2023-05-07 18:16:04
  • 安卓实现自定义圆形取色盘

    2022-01-14 18:01:55
  • 关于maven全局配置文件settings.xml解析

    2023-01-08 09:04:04
  • 详解Java的按位操作符

    2022-02-02 10:55:25
  • Java进程cpu占用过高问题解决

    2021-08-09 00:16:59
  • 一场由Java中Integer引发的踩坑实战

    2021-09-06 11:14:40
  • 详解Asp.Net MVC的Bundle捆绑

    2021-09-10 05:21:38
  • C#画笔使用复合数组绘制单个矩形的方法

    2022-03-20 01:41:09
  • Mybatis Select Count(*)的返回值类型介绍

    2022-06-17 12:51:19
  • sublime text3搭建配置c语言编译环境的详细图解教程(小白级)

    2021-12-16 09:18:27
  • Android 实现闪屏页和右上角的倒计时跳转实例代码

    2022-12-10 17:32:32
  • java.lang.NoSuchMethodException: com.sun.proxy.$Proxy58.list错误解决办法

    2021-05-25 03:11:19
  • Android实现文件上传和下载倒计时功能的圆形进度条

    2023-12-08 16:45:35
  • Java中Lambda表达式和函数式接口的使用和特性

    2023-06-20 20:05:42
  • Go Java算法猜数字游戏示例详解

    2022-03-02 21:01:50
  • Android基于OpenCV实现Harris角点检测

    2023-07-16 12:19:47
  • feignclient https 接口调用报证书错误的解决方案

    2021-08-20 18:35:55
  • asp之家 软件编程 m.aspxhome.com