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. Oracle Client 10g (instantclient) 精简版安装

    今天遇到个软件要求安装oracle client端,于是考虑装精简版本的,就从http://www.oracle.com/technology/software/tech/oci/instantcli ...

  2. POJ2226Muddy Fields

    题目:http://poj.org/problem?id=2226 巧妙建图:以行或列上的联通块作为点,每个泥格子作为边,求最小点覆盖就可以了! 于是用匈牙利算法找最大匹配.注意要对右部点记录每一个左 ...

  3. 东芝笔记本Satellite M40-A

    1. 问题:开机F2/Fn+F2进入不了BIOS 原因:当安装了Windows10/Windows8并且开启了快速启动,开机F2会进入不了BIOS或者F12进入不了U盘启动选择 解决方法:进入 开始- ...

  4. CentOS7 防火墙配置-详解

    CentOS 7 防火墙配置 1.防火墙的简述 防火墙对服务器起到一定的保护作用,所以了解一些相关的操作是很有必要的. 在CentOS 7.x中,有了一种新的防火墙策略叫FireWall , 在6.x ...

  5. 【python】常用的日期和时间操作

    #-*- coding: utf-8 -*- import datetime #给定日期向后N天的日期 def dateadd_day(days): d1 = datetime.datetime.no ...

  6. 面试总结之MISC(操作系统,网络,数学,软件开发,测试,工具,系统设计,算法)

    操作系统 解释堆和栈的区别. 分配在堆的内存与分配在堆栈的内存有什么不同 分配在堆的内存要手动去释放 线程与进程的区别 多线程中栈与堆是公有的还是私有的 在多线程环境下,每个线程拥有一个栈和一个程序计 ...

  7. 学习笔记之SQL / MySQL

    SQL Fiddle(在线执行SQL语句的网站) http://www.sqlfiddle.com/ MySQL https://www.mysql.com/ MySQL :: MySQL 5.7 R ...

  8. 使用JS获取当前地理位置方法汇总(如用谷歌接口,会出再以上报错,必须申请密钥并设置接受服务器IP!!!)

    RefererNotAllowedMapError 错误 加载 Google Maps JavaScript API 的当前 URL 尚未添加到允许的引用站点列表中.请在 Google API Con ...

  9. Educational Codeforces Round 37-E.Connected Components?题解

    一.题目 二.题目链接 http://codeforces.com/contest/920/problem/E 三.题意 给定一个$N$和$M$.$N$表示有$N$个点,$M$表示,在一个$N$个点组 ...

  10. C++11奇怪的语法

    1. istream_iterator 简而言之,istream_iterator像操作容器一样操作istream.例如下面代码,从std::cin构造std::istream_iteream< ...