1、静态成员函数、静态数据成员

在类中,用static修饰的成员函数被称为静态成员函数,而用static修饰的数据成员就称为静态数据成员;与普通的成员函数和数据成员不同,

静态成员函数和静态数据成员有自己独有的特点和用法,定义方法如下:

  class Tank{
public:
static void func(void); // 声明静态成员函数
..........
private:
static int m_iCount; // 声明静态数据成员
.......
} int Tank::m_iCount = ; // 初始化静态数据成员 void Tank::func(void) // 定义静态成员函数 注意不要加 static
{
.....
}

2、静态成员函数、静态数据成员与普通的成员函数、数据成员有什么区别?

(1)静态成员函数、静态数据成员依赖于具体的类,但是并不依赖于类实例化的对象。

当一个类定义完成之后,我们其实就可以调用这个类的静态成员函数和静态数据成员,而不必实例化一个类对象之后才能使用,

这点与非静态的成员函数和非静态的数据成员是不同的。例如下面所示:

 #include <iostream>
using namespace std; class Tank{
public:
Tank(void) { m_iCount++; }
~Tank(void) { m_iCount--; }
static void func(void); // 申明静态成员函数
static int m_iCount; // 声明静态数据成员
}; ......... // 省略了初始化静态数据成员和静态成员函数定义 int main(void)
{
Tank::func(); // 没有实例化类对象而直接使用静态成员函数
cout << Tank::m_iCount << endl; // 没有实例化类对象而直接使用静态数据成员
return ;
}

(2)静态成员函数不能调用非静态成员函数和非静态成员数据,但是非静态成员函数可以调用静态成员函数和静态成员数据。

这个其实是很好理解的,前面说过,静态成员函数、静态数据成员不依赖于实例化对象,只是随着类定义的出现而存在;

但是非静态数据成员必须是实例化一个具体的对象之后才存在一份属于这个对象的成员数据,而非静态成员函数虽然代码只有一份,

但是因为函数操作的成员数据是依赖于具体的对象的,所以导致成员函数也是依赖于对象的;所以在这种情况下,静态成员函数

是不能操作非静态数据成员和非静态成员函数的,因为先于非静态数据成员诞生,先于非静态成员函数被"激活",就好比是

:你都不知道后面会定义哪些具体的对象,你怎么能够提前就使用呢?但是静态成员函数是可以调用的静态数据成员的。

(3)静态数据成员在内存中只有一份,而非静态数据成员依赖于具体的对象,所以不同的对象都有一份非静态数据成员。

(4)静态数据成员必须单独初始化,不能在类构造函数中进行初始化,实例化类的大小中并不包括静态数据成员。

类的构造函数是实例化一个对象的时候才调用的,而静态数据成员不依赖于对象,所以不能使用构造函数来初始化一个静态数据成员。

 #include <iostream>
using namespace std; class Tank{
public:
Tank(char name) { m_cName = name; m_iCount++; } // 构造函数
~Tank(void) { m_iCount--; } // 析构函数
int getCount(void) { return m_iCount; }
static int func(void); // 申明静态成员函数
private:
char m_cName;
static int m_iCount; // 声明静态数据成员
}; int Tank::m_iCount = ; // 静态数据成员的初始化 int Tank::func(void)
{
return m_iCount;
cout << "Tank---func" << endl;
} int main(void)
{
Tank tank('A');
cout << sizeof(tank) << endl; // 测试大小
cout << Tank::func() << endl;
return ;
}

静态数据成员的初始化

(5)调用静态成员函数、静态数据成员与调用非静态成员函数、非静态数据成员不同。

静态成员函数、静态数据成员的调用方式有两种:在还没有实例化对象前 和 实例化对象之后,,代码如下:

 #include <iostream>
using namespace std; class Tank{
public:
Tank(char name) { m_cName = name; m_iCount++; } // 构造函数
~Tank(void) { m_iCount--; } // 析构函数
int getCount(void) { return m_iCount; }
static int func(void); // 申明静态成员函数
private:
char m_cName;
static int m_iCount; // 声明静态数据成员
}; int Tank::m_iCount = ; // 静态数据成员的初始化 int Tank::func(void)
{
return m_iCount;
cout << "Tank---func" << endl;
} int main(void)
{
cout << Tank::func() << endl; // 实例化对象之前 Tank tank('A'); cout << tank.func() << endl; // 实例化对象之后,也可以是 Tank::func() 两种都可以 return ;
}

调用非静态的方法

(6)在静态成员函数的参数列表中是没有带默认的this指针的,因为this指针是用来指向这个对象的地址的,而我们的静态成员函数不依赖于实例化对象而存在,所以是没有thsi指针的。

所以在函数声明的后面也是不能加上const来进行修饰的,否则编译是会出错的。

在C++中,本人对于 :: 和 . 的理解:   class Time;

:: 前面的一般都是一种数据类型,可以是结构体类型和类类型,例如 Time::func(); 表示func这个函数依赖于类(也就是数据类型),并不依赖与对象(也就是具体的变量);

. 前面的一般都是一个具体的对象(也就是变量),例如 Time time;  time.set(); 表示set函数依赖于这个对象(也就是变量),既然依赖于这个具体的对象;

以上纯属我自己的理解。

C++中static修饰的静态成员函数、静态数据成员的更多相关文章

  1. C++学习5-面向对象编程基础(构造函数、转换构造、静态数据成员、静态成员函数、友元)

    知识点学习 类 const作用 C语言的const限定符的含义为"一个不能改变值的变量",C++的const限定符的含义为"一个有类型描述的常量": const ...

  2. C++基础(静态数据成员和静态成员函数)

    [简介] 1.静态数据成员在类中声明,在源文件中定义并初始化: 2.静态成员函数没有this指针,只能访问静态数据成员: 3.调用静态成员函数:(1)对象.(2)直接调用: 4.静态成员函数的地址可用 ...

  3. C++ 静态数据成员和静态成员函数

    一 静态数据成员: 1.静态数据成员的定义. 静态数据成员实际上是类域中的全局变量.所以,静态数据成员的定义(初始化)不应该被放在头文件中,因为这样做会引起重复定义这样的错误.即使加上#ifndef ...

  4. C++静态数据成员与静态成员函数

    一般情况下,如果有n个同类的对象,那么每一个对象都分别有自己的数据成员,不同对象的数据成员各自有值,互不相干.但是有时人们希望有某一个或几个数据成员为所有对象所共有,这样可以实现数据共享. 可以使用全 ...

  5. 转:C语言中的static变量和C++静态数据成员(static member)

    转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序 ...

  6. 静态数据成员(面向对象的static关键字)

    静态数据成员: 在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员.先举一个静态数据成员的例子. #include<iostream> using namesp ...

  7. C++类中static修饰的函数的使用

    //在C++中应该养成习惯:只用静态成员函数引用静态成员数据,而不引用非静态成员数据 #include <iostream>using namespace std;class st_inf ...

  8. C++类静态数据成员与类静态成员函数

    from:://http://blog.csdn.net/taina2008/article/details/1684834 把类中的函数都定义成静态函数,这样相当于在编译时就分配了空间,这样不需要实 ...

  9. 《挑战30天C++入门极限》C++类静态数据成员与类静态成员函数

        C++类静态数据成员与类静态成员函数 在没有讲述本章内容之前如果我们想要在一个范围内共享某一个数据,那么我们会设立全局对象,但面向对象的程序是由对象构成的,我们如何才能在类范围内共享数据呢? ...

随机推荐

  1. 使用_beginThreadex创建多线程(C语言版多线程)

    _beginThreadex创建多线程解读 一.需要的头文件支持 #include <process.h>         // for _beginthread() 需要的设置:Proj ...

  2. 什么是HBase(六)性能调优

    硬件层面 内存要大,最好是ECC(Error Checking and Correcting),实现内存的动态纠错:CPU要多路(每个路彼此隔离)每个路一个CPU,每个cpu上面一般都是2~12核. ...

  3. bzoj 3730 震波——动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3730 查询一个点可以转化为查询点分树上自己到根的路径上每个点对应范围答案.可用树状数组 f ...

  4. java对图片的处理

    原文地址:http://www.blogjava.net/PrettyBoyCyb/archive/2006/11/13/80922.html java 中的图片处理是很让人头疼的一件事情.目前 ja ...

  5. oracle查看和修改最大连接数

    第一步,在cmd命令行,输入sqlplus 或者直接在plsql中打开command window 第二步,根据提示输入用户名与密码 1. 查看processes和sessions参数 1 2 3 4 ...

  6. [转]Spring 之 Log4j 的配置

  7. Lifecycle of an ASP.NET Web API Message

    ASP.NET Web API, as we know now, is a framework that helps build Services over HTTP. Web API was int ...

  8. CentOS6系统优化

    [root@xuliangwei ~]# cat /etc/redhat-release //系统环境CentOS6.6 CentOS release 6.6 (Final) [root@xulian ...

  9. 关于RDS for mysql中导入数据库set global event_scheduler =1 需要更多超级权限

    关于RDS中导入数据库set global event_scheduler =1 需要更多超级权限 报错提示 其实这个意思是 让mysql自动启动 计划任务 如果在 命令行下 查询  SHOW VAR ...

  10. python3操作MySQL数据库

    安装PyMySQL 下载地址:https://pypi.python.org/pypi/PyMySQL 1.把操作Mysql数据库封装成类,数据库和表先建好 import pymysql.cursor ...