在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻的认识。

第一个例子,通过类名调用静态成员函数和非静态成员函数

class Point

{

public:

void init()

{

}

static void output()

{

}

};

void main()

{

Point::init();

Point::output();

}

编译出错:error C2352: 'Point::init' : illegal call of non-static member function

结论1:不能通过类名来调用类的非静态成员函数。

第二个例子,通过类的对象调用静态成员函数和非静态成员函数

将上例的main()改为:

void main()

{

Point pt;

pt.init();

pt.output();

}

编译通过。

结论2:类的对象可以使用静态成员函数和非静态成员函数。

第三个例子,在类的静态成员函数中使用类的非静态成员

#include <stdio.h>

class Point

{

public:

void init()

{

}

static void output()

{

printf("%d\n", m_x);

}

private:

int m_x;

};

void main()

{

Point pt;

pt.output();

}

编译出错:error C2597: illegal reference to data member 'Point::m_x' in a static member function

因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。

结论3:静态成员函数中不能引用非静态成员。

第四个例子,在类的非静态成员函数中使用类的静态成员

class Point

{

public:

void init()

{

output();

}

static void output()

{

}

};

void main()

{

Point pt;

pt.output();

}

编译通过。

结论4:类的非静态成员函数可以调用用静态成员函数,但反之不能。

第五个例子,使用类的静态成员变量

#include <stdio.h>

class Point

{

public:

Point()

{

m_nPointCount++;

}

~Point()

{

m_nPointCount--;

}

static void output()

{

printf("%d\n", m_nPointCount);

}

private:

static int m_nPointCount;

};

void main()

{

Point pt;

pt.output();

}

按Ctrl+F7编译无错误,按F7生成EXE程序时报链接错误

error LNK2001: unresolved external symbol "private: static int Point::m_nPointCount" (?m_nPointCount@Point@@0HA)

这是因为类的静态成员变量在使用前必须先初始化。

在main()函数前加上int Point::m_nPointCount = 0;

再编译链接无错误,运行程序将输出1。

结论5:类的静态成员变量必须先初始化再使用。

结合上面的五个例子,对类的静态成员变量和成员函数作个总结:

一。静态成员函数中不能调用非静态成员。

二。非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。

三。静态成员变量使用前必须先初始化(如int MyClass::m_nNumber = 0;),否则会在linker时出错。

再给一个利用类的静态成员变量和函数的例子以加深理解,这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,一个静态成员函数输出这个双向链表。

#include <stdio.h>

#include <string.h>

const int MAX_NAME_SIZE = 30;

class Student

{

public:

Student(char *pszName);

~Student();

public:

static void PrintfAllStudents();

private:

char    m_name[MAX_NAME_SIZE];

Student *next;

Student *prev;

static Student *m_head;

};

Student::Student(char *pszName)

{

strcpy(this->m_name, pszName);

//建立双向链表,新数据从链表头部插入。

this->next = m_head;

this->prev = NULL;

if (m_head != NULL)

m_head->prev = this;

m_head = this;

}

Student::~Student ()//析构过程就是节点的脱离过程

{

if (this == m_head) //该节点就是头节点。

{

m_head = this->next;

}

else

{

this->prev->next = this->next;

this->next->prev = this->prev;

}

}

void Student::PrintfAllStudents()

{

for (Student *p = m_head; p != NULL; p = p->next)

printf("%s\n", p->m_name);

}

Student* Student::m_head = NULL;

void main()

{

Student studentA("AAA");

Student studentB("BBB");

Student studentC("CCC");

Student studentD("DDD");

Student student("MoreWindows");

Student::PrintfAllStudents();

}

程序将输出:

当然在本例还可以增加个静态成员变量来表示链表中学生个数,如果读者有兴趣,就将这个作为小练习吧。

转载请标明出处,原文地址:http://www.cnblogs.com/morewindows/archive/2011/08/26/2154198.html

转:C++ 类的静态成员详细讲解的更多相关文章

  1. 05-- C++ 类的静态成员详细讲解

     C++ 类的静态成员详细讲解    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不 ...

  2. 面向对象课后深入学习(C++ 类的静态成员详细讲解)

    今天在刚申请了博客,一下午都在写那个随笔,所以说好的来看c++的也放在了最后,下星期就考试了,这个类的静态成员是我不是很懂的,在网上 看到一片很详细的博客考下来回去慢慢看. 在C++中,静态成员是属于 ...

  3. C++ 类的静态成员详细讲解

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  4. C++ 类的静态成员详细讲解(转)

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  5. C++ 类的静态成员详细讲解[转]

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  6. 简单Java类 全网最详细讲解 !!!

    最近学习java非常吃力,学习的进度很快,由于基础没打牢固,整体上项目理解很吃力,偶尔会遇到一些基本的概念,都会阻碍整体的理解.最近也看了不少的视频讲解,听得很迷,最后搞得很乱,没有明确的学习目标,今 ...

  7. 【Cocos2d-X开发学习笔记】第12期:动作类CCAction的详细讲解

    一般对于游戏中的精灵而言,它们不仅仅是存在于场景中,而且是动态展现的,例如,精灵移动的动态效果.动 画效果.跳动效果.闪烁和旋转动态效果等.每一种效果都可以看成是精灵的一个动作. 一.动作类(CCAc ...

  8. [VC++]用CTime类得到当前日期、时间、星期,格式化(详细讲解)

    用CTime类得到当前日期.时间.星期,格式化(详细讲解)2009/05/12 09:48 A.M.① 定义一个CTime类对象 CTime time; ② 得到当前时间 time = CTime:: ...

  9. 第四节:详细讲解Java中的类和面向对象思想

    前言 大家好,给大家带来详细讲解Java中的类和面向对象思想的概述,希望你们喜欢 类和面向对象 在Java中怎样理解对象,创建对象和引用:什么是引用,对于基础学习的同学,要深入了解引用.示例:Stri ...

随机推荐

  1. C# 3.0 / C# 3.5 自动属性

    自动属性的好处 自动属性简化了我们在做 C# 开发的时候手写一堆私有成员 + 属性的编程方式,我们只需要使用如下方式声明一个属性,编译器就会自动生成所需的成员变量. 传统属性概念 属性的目的一是封装字 ...

  2. 4.Liunx磁盘管理

    1.磁盘管理:df .du 2.磁盘加载:mount. umount 3.磁盘分区:fdisk 1.df -h 查看硬件

  3. 【转】Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)

    E文好的可以直接看https://github.com/loresoft/EntityFramework.Extended 也可以在nuget上直接安装这个包,它的说明有点过时了,最新版本已经改用对I ...

  4. 主流Linux发行版简介

    发行版 包格式 所属厂商 发布年份 最新版本 说明 RHEL RPM RedHat 2004 7.3 RedHat Linux9.0后的企业方向,系统可以免费下载安装但无法使用官方yum源 Fedor ...

  5. 套接字编程,创建套接字socket

    1.套接字地址结构: struct sockaddr { sa_family_t sa_family; char sa_data[14]; }; 其中,成员sa_family表示套接字的协议族类型,对 ...

  6. Oracle中使用PL/SQL如何定义参数、参数赋值、输出参数和 if 判断

    1.pl/sql如何定义参数 declare --1)定义参数 -- ban_Id number; ban_Name ); 2.pl/sql如何参数赋值 --2)参数赋值-- ban_Id :; ba ...

  7. js之全局变量与window对象

    所有在全局作用域中声明的变量.函数都会变成window对象的属性和方法. 即: var age = 55; 可以通过window.age访问 然而全局变量和与在window对象上定义的属性还是有一点区 ...

  8. react中用pace.js

    pace.js不支持npm, 所以只能直接下载下来,当作普通js引入 我在用的时候怎么都引不到组件里去用 后来终于找到方法了,直接上图了 1.先将pace文件下载来放在公共js目录下,pace.les ...

  9. Java单例模式《二》懒汉式

    package com.study.mode; /** * 单例模式: 懒汉式,需要的时候创建. * @ClassName: SingleBean2 * @author BlueLake * @dat ...

  10. log4j的log4j.properties文件配置的详细介绍

    参考(common): http://blog.csdn.net/qq_30175203/article/details/52084127 参考2(log4j.additivity): http:// ...