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. IntelliJ IDEA 基础设置

    原文地址:IntelliJ IDEA 基础设置 博客地址:http://www.extlight.com 一.前言 IDEA 全称 IntelliJ IDEA,是java语言开发的集成环境,Intel ...

  2. winform 勾选可以改变框控件

    public partial class UCCheck : UserControl { [Browsable(true), Category("修改属性"), Descripti ...

  3. AngularJS开发指南14:依赖注入

    推荐两种使用场景: 1.控制器中的依赖注入 控制器是负责应用行为的类.推荐的控制器声明方法如下: var MyController = function(dep1, dep2) { ... } MyC ...

  4. Oracle SYS_CONTEXT用法

    1. USERENV(OPTION) 返回当前的会话信息. OPTION='ISDBA'若当前是DBA角色,则为TRUE,否则FALSE. OPTION='LANGUAGE'返回数据库的字符集. OP ...

  5. 黄聪:WordPress 多站点建站教程(二):后台(管理网络)设置详解,如何管理子站的用户、主题、插件、设置等功能

    建立好了子站,我们需要有个地方配置所有子站的主题.插件等功能,我们可以在后台看到 我的站点--管理网络 如下图: 在 管理网络--仪表盘 里面,我们可以创新用户和站点,也提供了查询功能. 要注意的是: ...

  6. Accept Job Offer Email Template

    Accept Job Offer Email Template <Date> <Hiring Manager’s name> <Company name> < ...

  7. 修改Gradle 和Maven本地仓库的位置方法

    本文转载自:https://www.cnblogs.com/dwb91/p/6523541.html 关于Maven的配置: 用过Maven的开发人员应该知道Maven可以通过配置 conf文件夹下面 ...

  8. selenium 笔记 2018

    1.指定浏览器驱动:dr = webdriver.Firefox(executable_path = '/Users/xxx/Documents/selenium_py/geckodriver/gec ...

  9. Python单例模式实现方法

    一  简介 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源 ...

  10. 1_boostrap概述

    1.bootstrap概述 1.1.什么是bootstrap?bootstrap的作用? Bootstrap,基于 HTML.CSS.JAVASCRIPT 的前端框架. 该框架已经预定义了一套CSS样 ...