当前位置: 首页 > 编程日记 > 正文

C++类的静态成员详细讲解

在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。

 

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻的认识。

第一个例子,通过类名调用静态成员函数和非静态成员函数

[cpp] view plaincopy
  1. class Point
  2. {
  3. public:
  4. void init()
  5. {
  6. }
  7. static void output()
  8. {
  9. }
  10. };
  11. void main()
  12. {
  13. Point::init();
  14. Point::output();
  15. }

编译出错:error C2352: 'Point::init' : illegal call of non-static member function

结论1:不能通过类名来调用类的非静态成员函数。

 

第二个例子,通过类的对象调用静态成员函数和非静态成员函数

将上例的main()改为:

[cpp] view plaincopy
  1. void main()
  2. {
  3. Point pt;
  4. pt.init();
  5. pt.output();
  6. }

编译通过。

结论2:类的对象可以使用静态成员函数和非静态成员函数。

 

第三个例子,在类的静态成员函数中使用类的非静态成员

[cpp] view plaincopy
  1. #include <stdio.h>
  2. class Point
  3. {
  4. public:
  5. void init()
  6. {
  7. }
  8. static void output()
  9. {
  10. printf("%d\n", m_x);
  11. }
  12. private:
  13. int m_x;
  14. };
  15. void main()
  16. {
  17. Point pt;
  18. pt.output();
  19. }

编译出错:error C2597: illegal reference to data member 'Point::m_x' in a static member function

因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。

结论3静态成员函数中不能引用非静态成员

 

第四个例子,在类的非静态成员函数中使用类的静态成员

[cpp] view plaincopy
  1. class Point
  2. {
  3. public:
  4. void init()
  5. {
  6. output();
  7. }
  8. static void output()
  9. {
  10. }
  11. };
  12. void main()
  13. {
  14. Point pt;
  15. pt.output();
  16. }

编译通过。

结论4:类的非静态成员函数可以调用用静态成员函数,但反之不能。

 

第五个例子,使用类的静态成员变量

[cpp] view plaincopy
  1. #include <stdio.h>
  2. class Point
  3. {
  4. public:
  5. Point()
  6. {
  7. m_nPointCount++;
  8. }
  9. ~Point()
  10. {
  11. m_nPointCount--;
  12. }
  13. static void output()
  14. {
  15. printf("%d\n", m_nPointCount);
  16. }
  17. private:
  18. static int m_nPointCount;
  19. };
  20. void main()
  21. {
  22. Point pt;
  23. pt.output();
  24. }

按Ctrl+F7编译无错误,按F7生成EXE程序时报链接错误

error LNK2001: unresolved external symbol "private: static int Point::m_nPointCount" (?m_nPointCount@Point@@0HA)

这是因为类的静态成员变量在使用前必须先初始化。

在main()函数前加上int Point::m_nPointCount = 0;

再编译链接无错误,运行程序将输出1。

结论5:类的静态成员变量必须先初始化再使用。

 

结合上面的五个例子,对类的静态成员变量和成员函数作个总结

一。静态成员函数中不能调用非静态成员。

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

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

 

再给一个利用类的静态成员变量和函数的例子以加深理解,这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,一个静态成员函数输出这个双向链表。

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <string.h>
  3. const int MAX_NAME_SIZE = 30;
  4. class Student
  5. {
  6. public:
  7. Student(char *pszName);
  8. ~Student();
  9. public:
  10. static void PrintfAllStudents();
  11. private:
  12. char    m_name[MAX_NAME_SIZE];
  13. Student *next;
  14. Student *prev;
  15. static Student *m_head;
  16. };
  17. Student::Student(char *pszName)
  18. {
  19. strcpy(this->m_name, pszName);
  20. //建立双向链表,新数据从链表头部插入。
  21. this->next = m_head;
  22. this->prev = NULL;
  23. if (m_head != NULL)
  24. m_head->prev = this;
  25. m_head = this;
  26. }
  27. Student::~Student ()//析构过程就是节点的脱离过程  
  28. {
  29. if (this == m_head) //该节点就是头节点。
  30. {
  31. m_head = this->next;
  32. }
  33. else
  34. {
  35. this->prev->next = this->next;
  36. this->next->prev = this->prev;
  37. }
  38. }
  39. void Student::PrintfAllStudents()
  40. {
  41. for (Student *p = m_head; p != NULL; p = p->next)
  42. printf("%s\n", p->m_name);
  43. }
  44. Student* Student::m_head = NULL;
  45. void main()
  46. {
  47. Student studentA("AAA");
  48. Student studentB("BBB");
  49. Student studentC("CCC");
  50. Student studentD("DDD");
  51. Student student("MoreWindows");
  52. Student::PrintfAllStudents();
  53. }

程序将输出:

当然在本例还可以增加个静态成员变量来表示链表中学生个数,如果读者有兴趣,就将这个作为小练习吧。

原文地址:http://blog.csdn.net/morewindows/article/details/6721430

转载于:https://www.cnblogs.com/heyonggang/p/3296378.html

相关文章:

jenkins2 multibranch

通过multibranch类型的pipeline job使得对于多个branch的支持更加简单。只需要创建一个multibranch job&#xff0c;jenkins将自动地为所有的branch创建job。 文章来自&#xff1a;http://www.ciandcd.com文中的代码来自可以从github下载&#xff1a; https://github.com/ciand…

Nagios的安装和基本配置(一:知识点总结及环境准备)

实验目的及要求 掌握Nagios监控的基本使用&#xff1b;掌握Nagios监控服务的搭建和配置&#xff1b; 实验环境&#xff1a; 1、满足实验要求的PC端&#xff1b; Host-name OS IP sofaware Nagios-server Centos7 192.168.1.119 Apache,php,Nagios,Nagios-plguins Nag…

浅谈Android四大组件之Service

一&#xff1a;Service简介 Android开发中&#xff0c;当需要创建在后台运行的程序的时候&#xff0c;就要使用到Service。 1:Service&#xff08;服务&#xff09;是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service&#xff0c;并且当用户切…

使用 fastlane 实现 iOS 持续集成(二)

本文接上篇文章主要说下怎样使用 fastlane 上传到fir和蒲公英&#xff0c;下面先介绍下 plugin 命令。 plugin命令介绍: 列出所有可用插件 fastlane search_plugins 搜索指定名称的插件: fastlane search_plugins [query] 添加插件: fastlane add_plugin [name] 安装插件: fast…

Nagios的安装和基本配置(二:Nagios-Server的安装)

任务二、Nagios-server的安装 2.1、创建Nagios用户和组 注&#xff1a; #useradd Nagios -s /bin/nologin #groundadd nagcmd #usermod -a -G nagcmd Nagios #usermod -a G nagcmd apache 2.2、安装Nagios 2.2.1、上传软件包至操作系统中&#xff1b; 2.2.2、解压软件并…

shell编程-正则表达式

1.正则表达式是什么 它主要用于字符串的模式分割&#xff0c;匹配&#xff0c;查找及替换操作。 2、正则表达式与通配符 正则表达式用来在文件中匹配符合条件的字符串&#xff0c;正则包含匹配。grep,awk,sed等命令可以支持正则表达式。 通配符用来匹配符合条件的文件名&#x…

使用 CocoaPods 给微信集成 SDK 打印收发消息

推荐序 本文介绍的是一套逆向工具&#xff0c;可以在非越狱手机上给任意应用增加插件。在文末的示例中&#xff0c;作者拿微信举例&#xff0c;展示出在微信中打印收发消息的功能。 这套工具可以加快逆向开发的速度&#xff0c;其重签名思想也可以用于二次分发别人的应用。 其实…

数据库之子查询四(多重,表复制)

一、多重子查询 select teaID,teaName,age,sex,dept,professionfrom tteacherwhere dept(select dept from teaIDt103265)and profession(select professionfrom tteacherwhere teaIDt103265)这里的子查询就是为了从表中提取出有效信息参与外部查询二、create table 语句中子查…

Nagios的安装和基本配置(三:Nagios-Client的安装)

任务三、Nagios-Client的安装 3.1、关闭防火墙和selinux 注&#xff1a; #systemctl stop firewalld.service #systemctl disable firewalld.service #vi /etc/selinux/config 3.2、配置环境 #yum install gcc glibc-common -y #yum install gd gd-devel openssl openssl…

事件(待完成)

内容窗口 事件绑定​ 给整个浏览器 内容窗口区的事件绑定。 ​通过 document.documentElement或者document.body&#xff1f;似乎都可以。但最好是直接通过document document.addEventListener(mousemove,function () { });// 整个浏览器内容范围都将触发。拖动实现必用​ 转载…

iOS 模仿支付宝支付到账推送,播报钱数

最近申请了支付宝的二维码收钱码&#xff0c;其中支付宝有这么一个功能&#xff0c;就是&#xff0c;别人扫描你的二维码给你转账之后&#xff0c;收到钱会有一条语音推送&#xff0c;”支付宝到账 1000万“之类的推送消息&#xff0c;不管你的支付宝app有没有被杀死。 只要你的…

hdu - 4707 - Pet

题意&#xff1a;一棵N个结点(编号从0开始)的树&#xff0c;根结点为0&#xff0c;求到根结点的距离大于D的结点个数&#xff08;0 < 测试组数T < 10, 0<N<100000, 0<D<N&#xff09;。 题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid4707…

Nagios的安装和基本配置(四:调试验证 错误总结)

任务四、调试验证 4.1、验证连通性 在/usr/local/Nagios/etc/nrpe.cfg文件中server的ip地址 #vi /usr/local/Nagios/etc/nrpe.cfg #重启nrpe #pkill nrpe #netstat -Intp #/usr/local/Nagios/bin/nrpe -d -c /usr/local/Nagios/etc/nrpe.cfg #在server主机做验证 #cd /…

hitTest和pointInside方法

hittest方法 就是用来寻找最合适的view当一个事件传递给一个控件&#xff0c;就会调用这个控件的hitTest方法点击了白色的view&#xff1a; 触摸事件 -> UIApplication -> UIWindow 调用 [UIWindow hitTest] -> 白色view [WhteView hitTest] 实验1: 定义 BaseView&…

Github上的PHP资源汇总大全

依赖管理 ——用于依赖管理的包和框架 Composer/Packagist : 一个包和依赖管理器 Composer Installers: 一个多框架Composer库安装器 Pickle: 可以在任意平台上安装PHP扩展包 依赖管理的附加部分 ——其它依赖管理的相关工具 Satis : 静态的Composer库生成器 Composition: 一个…

UIButton长按事件

添加长按事件1 - (void)viewDidLoad2 {3 [super viewDidLoad];4 //Do any additional setup after loading the view, typically from a nib.5 6 UIButton *aBtn[UIButton buttonWithType:UIButtonTypeRoundedRect];7 [aBtn setFrame:CGRectMake(0, 10, 60, 60…

Hadoop集群搭建(一:集群安装及网络环境配置)

实验目的及要求 完成VMware workstations安装&#xff0c;会应用相关操作&#xff1b;完成虚拟机中Linux CentOS 7操作系统安装&#xff1b;完成静态网络地址的配置&#xff0c;所有主机的网络能够正常使用&#xff0c;相互之间能够正常连接&#xff1b;完成主机名配置&#x…

QQ音乐API分析记录

我一直是QQ音乐的用户&#xff0c;最近想做一个应用&#xff0c;想用QQ音乐的API&#xff0c;搜索了很久无果&#xff0c;于是就自己分析QQ音乐的API。 前不久发现QQ音乐出了网页版的&#xff0c;是Flash的&#xff0c;但是&#xff0c;我用iPhone打开这个链接的时候&#xff0…

Vision 圖像識別框架的使用

阅读 137收藏 102017-10-18原文链接&#xff1a;www.itread01.comGoogle无人车之父、MIT/斯坦福/耶鲁专家带你进入无人驾驶之域 http://cn.udacity.com/course/intro-to-self-driving-cars--nd113 本文為CocoaChina網友 品位生活 投稿 北京時間2017.6.6日淩晨1點&#xff0c;新…

Jmeter性能测试 入门

Jmeter性能测试 入门 原文:Jmeter性能测试 入门Jmeter是一款优秀的开源测试工具&#xff0c; 是每个资深测试工程师&#xff0c;必须掌握的测试工具&#xff0c;熟练使用Jmeter能大大提高工作效率。 熟练使用Jmeter后&#xff0c; 能用Jmeter搞定的事情&#xff0c;你就不会使用…

Hadoop集群搭建(二:集群主机间免密登录配置)

实验目的及要求&#xff1a; 静态网络地址配置&#xff1b;主机名的配置&#xff1b;防火墙的配置&#xff0c;使平台相关软件的常用端口能够远程正常访问&#xff1b;主机地址映射的配置&#xff0c;使所有主机能够通过主机名相互正常访问&#xff1b;免密码登录的配置&#…

你真的会用 CocoaPods 吗?

CocoaPods 可以说是 iOS 开发应用最广泛的包管理工具&#xff0c;本篇文章主要介绍 CocoaPods 的第三方库是怎样从网络集成到我们本地的项目当中&#xff0c;也是制作私有库、开源库和 iOS 项目组件化的一个知识铺垫。 让我们从一张图片开始&#xff1a; CocoaPods 工作流程 …

【spring 5】AOP:spring中对于AOP的的实现

在前两篇博客中&#xff0c;介绍了AOP实现的基础&#xff1a;静态代理和动态代理&#xff0c;这篇博客介绍spring中AOP的实现。 一、采用Annotation方式 首先引入jar包&#xff1a;aspectjrt.jar && aspectweaver.jar applicationContext配置文件&#xff1a; <span…

通过BeanShell获取UUID并将参数传递给Jmeter

有些HTTPS请求报文的报文体中包含由客户端生成的UUID&#xff0c;在用Jmeter做接口自动化测试的时候&#xff0c;因为越过了客户端&#xff0c;直接向服务器端发送报文&#xff0c;所以&#xff0c;需要在Jmeter中通过beanshell获取UUID&#xff0c;并能将参数传递给Jmeter&…

Hadoop集群搭建(四:Zookeeper环境安装)

实验 目的 要求 目的&#xff1a; 1、掌握在完全分布模式的整合平台中Zookeeper的完全分布模式的安装 要求&#xff1a; 完成Zookeeper的完全分布农事的安装&#xff1b;Zookeeper服务能够正常启动和连接&#xff1b;Zookeeper控制台能够正常进入&#xff1b;Zookeeper控制台命…

史上第二走心的 iOS11-Drag Drop 教程

原文链接&#xff1a;www.jianshu.com只需完成个人实名注册&#xff0c;即可获得腾讯云免费套餐&#xff01;云服务器CVM、云数据库 MYSQL、文件存储 CFS.....应有尽有&#xff01;https://cloud.tencent.com/act/free 话不多说&#xff0c;先上效果图 普通view拖拽效果 TableV…

指针的各式定义

1&#xff0c;一个整形数&#xff1a; int a; 2&#xff0c;一个指向整形数的指针&#xff1a; int *a; 3&#xff0c;一个指向指针的指针&#xff0c;它指向的指针指向一个整形数&#xff1a; int **a; 4&#xff0c;一个有10个整形数的数组&#xff1a; int a[10]; 5&#…

AS 400 常用命令

转自&#xff1a;http://blog.chinaunix.net/uid-22375044-id-3049793.html 一、命令技巧 命令构成&#xff1a; CRT* (Creat) 创建 WRK* (Work With) 操作 RMV* (Remove) 去除 DSP* (Display) 显示 ADD* (Add) 添加 CHG* (Change) 改变 DLT* (Delete) 删除 CFG* (Config) 配置…

Hadoop集群搭建(五:Hadoop HA集群模式的安装)

实验 目的 要求 目的&#xff1a; 1、Hadoop的高可用完全分布模式的安装和验证 要求&#xff1a; 完成Hadoop的高可用完全分布模式的安装&#xff1b;Hadoop的相关服务进程能够正常的启动&#xff1b;HDFS能够正常的使用&#xff1b;MapReduce示例程序能够正常运行&#xff1b…

iOS开发业界毒瘤 Hook

原文地址 为什么有这篇博文 不知道何时开始iOS面试开始流行起来询问什么是 Runtime&#xff0c;于是 iOSer 一听 Runtime 总是就提起 MethodSwizzling&#xff0c;开口闭口就是黑科技。但其实如果读者留意过C语言的 Hook 原理其实会发现所谓的钩子都是框架或者语言的设计者预留…