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. Windows 7 x64 安装 Oracle 11g Express

    1. 下载    在这里下载文件: Oracle Database Express Edition 11g Release 2 for Windows x32    Oracle 不提供 window ...

  2. 容器平台选型的十大模式:Docker、DC/OS、K8S谁与当先?

    首先我们来谈什么情况下应该使用Docker的问题   如图,左面是经常挂在嘴边的所谓容器的优势,但是虚拟机都能一一怼回去. 如果部署的是一个传统的应用,这个应用启动速度慢,进程数量少,基本不更新,那么 ...

  3. Spring整合Hibernate,Druid(Maven)

    本文转载自:http://blog.csdn.net/lantazy/article/details/52495839 首先,说一下spring,spring有很好的整合能力,Web应用的各个层次都能 ...

  4. Rhythmk 学习 Hibernate 05 - Hibernate 表间关系 [ManyToOne,OneToMany]

    1.项目结构: 1.1.场景说明: 一个订单,包含多个产品 1.2.类文件: Order.java package com.rhythmk.model; import java.util.Date; ...

  5. DevExpress GridView 整理

    1:去除 GridView 头上的 "Drag a column header here to group by that column" -->  点击 Run Desig ...

  6. Spring cloud config-client 爬坑

    配置文件 找不到属性 Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'from' in st ...

  7. JS 位数不够自动左补0

    var mycode = "11"; mycode = (Array(4).join(0) + parseInt(mycode)).slice(-4);//0011 mycode1 ...

  8. Git----分支管理01

    分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN. 如果两个平行宇宙互不干扰,那对现在的你也没有啥影响,不过,在某个时间点,两个平行宇宙合 ...

  9. BeanUtils.copyProperties不能copy复杂对象List的解决方式

    需要注意的就是把List拆分,遍历add,然后把list设置到返回对象中 package test.test; import java.util.ArrayList; import java.util ...

  10. 小学生轻松做题App

    作业链接:https://edu.cnblogs.com/campus/fzzcxy/2016SE/homework/2180 原型模型设计工具:墨刀 原型模型链接:https://modao.cc/ ...