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

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;
}

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

(0)

相关推荐

  • C++中静态成员函数访问非静态成员的实例

    C++中静态成员函数访问非静态成员的实例 实现代码: #include <iostream> /* 静态成员函数只能访问静态数据成员.静态成员函数和类以外的函数和数据,不能访问非静态数据成员,但静态成员函数或静态数据成员可由任意访问许可的函数访问.原因是:当前对象的地址(this)是被隐含地传递到被调用的函数的.但一个静态成员函数没有this指针,所以它无法访问非静态的成员函数. */ class a { public: static void FunctionA()//静态成员函数没有隐含的

  • C++中的局部变量、全局变量、局部静态变量、全局静态变量的区别

    局部变量(Local variables)与 全局变量: 在子程序或代码块中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量. 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序或代码块. 当全局变量与局部变量同名时:在定义局部变量的子程序内,局部变量起作用:在其它地方全局变量起作用. 全局变量在程序开始运行期间就已经在内存中开辟了内存空间,直到程序结束才会释放这块内存空间. 全局变量要在其他文件中使用,需显示的声明这个变量,使用extern关键字声明(extern int

  • C++ 实现静态链表的简单实例

    C++ 实现静态链表的简单实例 用数组描述的链表,即称为静态链表. 在C语言中,静态链表的表现形式即为结构体数组,结构体变量包括数据域data和游标cur. 这种存储结构,仍需要预先分配一个较大的空间,但在作为线性表的插入和删除操作时不需移动元素,仅需修改指针,故仍具有链式存储结构的主要优点. 下图表示了静态链表的一中存储结构: 图中用彩色途上的是两个头结点,不存放数据,分别用来记录第一个备用节点和第一个数据节点的下标. 下面给出静态链表的C++实现代码: 首先给出头文件:StaticList.

  • C++静态成员变量和静态成员函数的使用方法总结

    一.静态成员变量: 类体中的数据成员的声明前加上static关键字,该数据成员就成为了该类的静态数据成员.和其他数据成员一样,静态数据成员也遵守public/protected/private访问规则.同时,静态数据成员还具有以下特点: 1.静态数据成员的定义. 静态数据成员实际上是类域中的全局变量.所以,静态数据成员的定义(初始化)不应该被放在头文件中. 其定义方式与全局变量相同.举例如下: xxx.h文件 class base{ private: static const int _i;//

  • 详解C++的JSON静态链接库JsonCpp的使用方法

    JsonCpp部署方法: 在http://sourceforge.net/projects/jsoncpp/中下载最新版本的jsoncpp库源码. 之后将jsoncpp-src-版本号-tar.gz解压出来,打开makefiles中的jsoncpp.sln进行编译,之后build文件夹下的vs71\debug\lib_json中会有一个.lib静态链接库. JsonCpp主要包含三种类型的class:Value Reader Writer. jsoncpp中所有对象.类名都在namespace

  • C/C++静态类和this指针详解及实例代码

     C/C++静态类和this指针详解 1.静态类 C++的静态成员不仅可以通过对象来访问,还可以直接通过类名来访问. class CBook{ public: static double price;//需要通过类外来进行初始化 } int main(void){ CBook book; book.price;//通过对象来访问 CBook::price//通过类名来访问 return 0; } 静态成员变量 对应静态成员有以下几点需要注意: (1)静态数据成员可以是当前类的类型,而其他数据成员

  • C++ 静态成员的类内初始化详解及实例代码

    C++ 静态成员的类内初始化详解及实例代码 一般来说,关于C++类静态成员的初始化,并不会让人感到难以理解,但是提到C++ 静态成员的"类内初始化"那就容易迷糊了. 我们来看如下代码: //example.h #include<iostream> #include<vector> using namespace std; class Example{ public: static double rate = 6.5; static const int vecSi

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

    C++中静态成员函数与静态成员变量(static ) 这篇介绍了静态成员函数与静态成员变量,是我的读书笔记,我希望它够简短但又比较全面,起到复习的作用.如果有一些C++知识记不清楚了,它可以帮你很快回忆起来. 复习C语言的static关键字 (1)加在局部变量的前面使之成为静态局部变量,作用域还是在函数内部,可是生存周期延长了. (2)加在全局变量的前面限定该变量作用域为文件作用域,就是说即使其他文件使用了extern扩展作用域也不行.这在C语言的多人项目中非常有用,避免了变量的重名.然而在C+

  • Angular外部使用js调用Angular控制器中的函数方法或变量用法示例

    本文实例讲述了Angular外部使用js调用Angular控制器中的函数方法或变量.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html ng-app="myApp" id="myApp"> <head> <meta name="viewport" content="width=device-width" /> <title>Test</

  • 浅谈js中同名函数和同名变量的执行问题

    经测试未写成闭包形式的在同一个文件中或者不同的 js 文件中定义的同名函数,调用时会执行后面一个定义的函数.即使这样写也会执行后面一个即会弹出2: <script type="text/javascript"> function t(){ alert(1); } t(); function t(){ alert(2); } </script> 另外,定义的变量与css样式也是以后面的为准. 但是对于函数,经测试这样写却会执行前面的函数直接量即弹出1,暂时不知道是

  • 深入解析C++编程中的静态成员函数

    C++静态成员函数 与数据成员类似,成员函数也可以定义为静态的,在类中声明函数的前面加static就成了静态成员函数.如 static int volume( ); 和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分. 如果要在类外调用公用的静态成员函数,要用类名和域运算符"::".如 Box::volume( ); 实际上也允许通过对象名调用静态成员函数,如 a.volume( ); 但这并不意味着此函数是属于对象a的,而只是用a的类型而已. 与静态数据成员不同,静态成

  • 关于C++静态成员函数访问非静态成员变量的问题

    复制代码 代码如下: class a{public:  static FunctionA()  {     menber = 1;  } private:  int menber;} 编译上述代码,出错.原因很简单大家都知道,静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存.静态成员函数没有隐含的this自变量.所以,它就无法访问自己类的非静态成员. 那要想访问怎么办呢?地球人都知道只要将: 复制代码 代码如下: int me

  • C++静态成员函数不能调用非静态成员变量(详解)

    其实我们从直观上可以很好的理解静态成员函数不能调用非静态成员变量这句话因为无论是静态成员函数还是静态成员变量,它们 都是在类的范畴之类的,及在类的整个生存周期里始终只能存在一份.然而非静态成员变量和非静态成员函数是针对类的对象而言. 然而从本质上来说类的静态成员函数的函数形参中没有默认的this指针,导致不能调用具体实例对象的成员. 下面我们来测试一下: 先在静态成员函数中调用静态成员变量: #include <iostream> using namespace std; class vpoe

  • C++的静态成员变量和静态成员函数你了解多少

    目录 静态成员变量 静态变量在任何类对象创建前初始化 定义静态成员变量 使用静态成员变量 类对象共享静态成员 constconstexpr 静态成员函数 总结 静态成员变量 这里先引用GeeksforGeeks的一段内容: Static data members are class members that are declared using static keywords. A static member has certain special characteristics. These

  • C++类静态成员与类静态成员函数详解

    当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享.各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义了多少类对象无关.静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关. 静态数据成员的用途之一是统计有多少个对象实际存在. 静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的.也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一

  • C++分析讲解类的静态成员函数如何使用

    目录 一.未完成的需求 二.问题分析 三.静态成员函数 四.小结 一.未完成的需求 统计在程序运行期间某个类的对象数目 保证程序的安全性(不能使用全局变量) 随时可以获取当前对象的数目 在[C++基础入门]20.C++中类的静态成员变量中每次打印对象的个数时,都需要依赖于一个对象名,下面看一个代码: #include <stdio.h> class Test { public: static int cCount; public: Test() { cCount++; } ~Test() {

  • C++中回调函数(CallBack)的用法分析

    本文实例分析了C++中回调函数(CallBack)的用法.分享给大家供大家参考.具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过. 其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即"this"指针,C++通过传递this指针给其成员函数从而实现程序函数可以访问C++的数据成员.这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员.由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时

随机推荐