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

1.静态成员

1.静态数据成员与全局变量一样都是静态分配存储空间的,在编译时,就要为类的静态数据成员分配存储空间。但全局变量在程序中的任何位置都可以访问它,而静态数据成员受到访问权限的约束。必须是public权限时,才可能在类外进行访问。

2.静态数据成员的初始化

(1)*静态数据成员初始化是在类的文件(.cpp),而不是在类的头文件(.h)中进行的。这是因为类声明位于头文件中,程序可能将头文件包括在其他几个文件中。如果在头文件中进行初始化,将出现多个初始化语句副本,从而引发错误。

A.h文件

class A

{

private:

static int a;
};

A.cpp文件

int A::a = 0;   //数据类型 类名::静态数据成员名 = 初值。

(2)因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员。

(3)静态成员变量在类中仅仅是声明(声明只是表明了变量的数据类型和属性,并不分配内存),没有定义,所以要在类的外面定义(定义给静态成员变量分配内存)。

class A

{

public:

static int a;   //声明但未定义

};

int main()

{

printf("%d", A::a);   //error。   a没分配内存,不能访问。

return 0;

}

class A

{

public:

static int a;   //声明但未定义

};

int A::a = 3;   //定义了静态成员变量,同时初始化。也可以写"int A:a;",即不给初值,同样可以通过编译。

int main()

{

printf("%d", A::a);//ok。a分配了内存,可以访问。

return 0;

}

(4)注意:静态数据成员在类声明中声明,在包含类方法的文件中初始化。

3.静态成员能在类的范围内共享。在类中,静态成员可以实现多个对象之间的数据共享。它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值。

4.类的静态成员是可以独立访问的,也就是说,不需要创建类的实例就可以访问静态成员。

5.派生类对象与基类对象共享基类静态数据成员

class base

{

public:

static int _num; //声明静态成员

};

int base::_num=0; //静态数据成员的真正定义

class derived : public base

{

};

main()

{

base a;

derived b;

a._num++;

cout<<a._num<<endl;

b._num++;

cout<<b._num<<endl;

cout<<a._num<<endl;

}

运行结果:1 2 2

 

6.静态数据成员的类型可以是所属类的类型,而普通数据成员则不可以。普通数据成员的只能声明为所属类类型的指针或引用。

class base


public : 
static base a;//正确,静态数据成员 
base b;//错误 
base *p;//正确,指针 
base &m;//正确,引用 
};

7.静态数据成员的值const成员函数可以被合法的改变

base.h文件

class base

{

public:

base() { i = 0; }

private:

static int a;

int i;

void test() const   //const 成员函数

{

a++;//正确,static数据成员

i++;//错误

}

};

base.cpp文件

int base::a = 0;

2.静态成员函数

1.静态函数是使用 static 修饰符修饰的函数,静态函数没有 this 指针,只能访问静态成员

2.调用静态成员函数(只能访问静态成员)

(1)对象可调用静态成员函数

(2)可直接调用静态成员函数

class Obj

{

static int i;

public:

Obj() { i++; cout << ’a’; }

~Obj() { i--; cout << ’b’; }

static int getVal() { return i; }   //静态成员函数(只能访问静态成员)

};

int Obj::i = 0;   //静态成员初始化

void f() { Obj ob2; cout << ob2.getVal(); }   //1.对象可调用静态成员函数

void main()

{

Obj ob1;

f();

Obj *ob3 = new Obj;   //new新建一个对象,再将该对象的指针赋值给指针ob3

cout << ob3->getVal();

delete ob3;

cout << Obj::getVal();   //2.可直接调用静态成员函数    输出:aa2ba2b1b

}

3.在类中如果函数调用的结果不会访问或者修改任何对象数据成员,这样的成员声明为静态成员函数比较好。

4.类的静态成员函数可以访问类的私有成员,但是静态成员函数只能直接访问类的静态私有成员,因为静态成员函数是不可以直接访问非静态的成员的。

5.静态成员函数可以借助对象名指针访问类的非静态私有成员

class DATA

{

private:

int i;   //非静态私有成员

static int j;   //静态数据成员

public:

DATA(int num) { i = num; j += num; }

static show(DATA c)

{

cout << ”i = ” << c.i << ”, j = ” << j << endl;   //非静态成员i(用对象名来引用);静态成员(直接引用)。

}

};

int DATA::j = 2;

void main()

{

DATA a(2), b(4);

DATA::show(a);

DATA::show(b);

}

输出:

i = 2, j = 8

i = 4, j = 8

6.不能把静态成员函数定义为虚函数。静态成员函数也是在编译时分配存储空间,所以在程序的执行过程中不能提供多态性。

7.*静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用类成员函数指针来储存。

base.h文件

class base

{

public:

static int func1();

int func2();

};

base.cpp文件

main()

{

int(*pf1)() = &base::func1;

int (base::*pf2)() = &base::func2;

}

真实案例:

DDPlatform.h文件

/*

登陆状态回调

ulState: 当前登陆状态

ulUserHandle: 登陆成功后的用户句柄,ucState==LOGIN_SUCCEED时值有效

ulALCHandle: 报警服务器句柄,ucState==LOGIN_SUCCEED时值有效

*/

typedef void (CALLBACK *fLoginStateCallback)(ULONG ulState, ULONG ulUserHandle, ULONG ulALCHandle);

/*

设备状态改变回调

ulCameraID: 设备ID

ulState: 当前状态

ulUserHandle: 登陆用户句柄

ulALCHandle: 报警服务器句柄

*/

typedef void (CALLBACK *fCameraRestateCallback)(ULONG ulCameraID, ULONG ulState, ULONG ulUserHandle, ULONG ulALCHandle);

struct PE_REGCALLBACK

{

fLoginStateCallback cbLoginState;

fCameraRestateCallback cbCameraRestate;

};

AlarmSystemWindow.h文件

#pragma once

#include "DDPlatform.h"

#include <BaseWidget.h>

class AlarmSystemWindow : public BaseWidget

{

Q_OBJECT

public:

AlarmSystemWindow(QWidget *parent);

~AlarmSystemWindow();

public:

static void CALLBACK LoginState(ULONG ulState, ULONG ulUserHandle, ULONG ulALCHandle);

static void CALLBACK CameraRestate(ULONG ulCameraID, ULONG ulState, ULONG ulUserHandle, ULONG ulALCHandle);

private:

PE_REGCALLBACK m_cbRegister;

priate:

void init();

};

AlarmSystemWindow.cpp文件

void AlarmSystemWindow::init()

{

memset(&m_cbRegister, 0, sizeof(m_cbRegister));

m_cbRegister.cbLoginState = LoginState;   //静态成员函数的地址可用普通函数指针储存

m_cbRegister.cbCameraRestate = CameraRestate;

bool RegisterCallback = DDPlatform::DDPlat_RegisterCallback(m_cbRegister);

}

void CALLBACK AlarmSystemWindow::LoginState(ULONG ulState, ULONG ulUserHandle, ULONG ulALCHandle)

{

AlarmSystemWindow* pThat = (AlarmSystemWindow*)g_AlarmWindow;

if (ulState == LOGIN_SUCCEED)

{

pThat->g_ulLoingUserHandle = ulUserHandle;

pThat->sglSendLoginHandle(ulUserHandle);   //发送登录句柄

}

else if (ulState == LOGIN_QUERERR || ulState == LOGIN_CONNERR || ulState == LOGIN_LOGINERR || ulState == LOGIN_AUTHFAIL)

{

}

}

void CALLBACK AlarmSystemWindow::CameraRestate(ULONG ulCameraID, ULONG ulState, ULONG ulUserHandle, ULONG ulALCHandle)

{

AlarmSystemWindow* pThat = (AlarmSystemWindow*)g_AlarmWindow;

//获取设备报警状态

if (ulState == CAMERAST_ALARMING) {   //报警中

pThat->sglSendAlarmDeviceData(ulCameraID);

}

}

注意:回调函数是将一个函数的指针作为另一个函数的参数,当另一个函数执行完后再执行该函数。

博客园的这个文本编辑实在是太难搞了,就这样吧...强迫症的我也屈服了

原文地址:https://www.cnblogs.com/tingtaishou/p/11977775.html

时间: 2024-10-14 00:32:10

C++基础(静态数据成员和静态成员函数)的相关文章

sdut 3-6 静态数据成员与静态成员函数

3-6 静态数据成员与静态成员函数 Time Limit: 1000MS Memory limit: 65536K 题目描述 通过本题目的练习可以掌握静态数据成员和静态成员函数的用法 要求设计一个点类Point,它具有两个double型的数据成员x,y.和一个静态数据成员count ,用以记录系统中创建点对象的数目.为该类设计构造函数和析构函数,在其中对count的值做修改,体现点的数目的动态变化.并为其添加一个静态成员函数用以输出count的值:成员函数showPoint()用于输出点的信息.

静态数据成员与静态成员函数

静态属性不是类中每个对象拥有的,而是共有的.由于静态成员逃离了对象而存在的性质,所以该实体应该在所有对象产生之前产生,更适合的时机是在程序启动的时候做初始化.初始化时候不可重复上static,但是要加上类名空间.该实体在程序中的唯一性,要求他不可以和类的定义放在头文件中,但是它确实是类的成员,所以放在类实现中最合适.如下: //--------------------Student.h ---类定义的文件 class Student{ private: static int num; } //-

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

一 静态数据成员: 1.静态数据成员的定义. 静态数据成员实际上是类域中的全局变量.所以,静态数据成员的定义(初始化)不应该被放在头文件中,因为这样做会引起重复定义这样的错误.即使加上#ifndef #define #endif或者#pragma once也不行. 其定义方式与全局变量相同.举例如下: xxx.h文件 class base{ private: static const int _i;//声明,标准c++支持有序类型在类体中初始化,但vc6不支持. }; xxx.cpp文件 con

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

一般情况下,如果有n个同类的对象,那么每一个对象都分别有自己的数据成员,不同对象的数据成员各自有值,互不相干.但是有时人们希望有某一个或几个数据成员为所有对象所共有,这样可以实现数据共享. 可以使用全局变量来达到共享数据的目的.例如在一个程序文件中有多个函数,每一个函数都可以改变全局变量的值,全局变量的值为各函数共享.但是用全局变量的安全性得不到保证,由于在各处都可以自由地修改全局变量的值,很有可能偶然失误,全局变量的值就被修改,导致程序的失败.因此在实际工作中很少使用全局变量. 如果想在同类的

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

当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享.各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义了多少类对象无关.静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关. 静态数据成员的用途之一是统计有多少个对象实际存在. 静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的.也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一

静态数据成员和函数

静态数据成员 类是类型而不是具体的数据对象,类的对象都是该类的实例,每个类对象都具有自己的数据成员,而且是相互独立,各占内存空间.然而,程序中往往需要让类的所有对象在类的范围内共享某个数据.声明为static的类成员能够在类的范围中共享,称之为静态成员. 一.全局变量与静态数据成员 希望在同类的多个对象之间实现数据共享,可以用静态的数据成员实现. 使用静态数据成员不会破坏隐藏的原则,即保证了安全性. 二.静态数据成员特点 在每个类中只有一个拷贝,由该类的所有对象共同维护和使用静态数据成员的值对每

在c++中,静态数据成员可以被非静态成员函数调用吗?如果可以调用的话那为什么还要定义静态成员函数呢

静态数据成员可以被非静态成员函数访问.但静态成员函数只能访问静态数据成员.静态数据成员从属于某一个类,而不是某一个类的 对象.同理,静态成员函数也是一样. 追问 定义静态成员函数的作用有何在呢 回答 静态成员函数隶属于类,不用实例化对象,就可以直接调用静态成员函数来操作静态数据成员 提问者评价 太给力了,你的回答完美解决了我的问题!

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

转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序运行期间,但作用域与自动变量相同,只能在定义该变量的函数内使用.退出该函数后, 尽管该变量还继续存在,但不能使用它.        b.对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值.而对自动变量不赋初值,则其值是不定的.2).static全局变量        全局变量本身就是静

c++:静态数据成员

一 . 静态数据成员 类体中的数据成员的声明前加上static关键字,该数据成员就成为了该类的静态数据成员.和其它数据成员一样,静态数据成员也遵守public/protected/private访问规则.同时,静态成员还具有以下特点: 1. 静态数据成员的定义. 静态数据成员实际上是类域中的全局变量.所以,静态数据成员的定义不应该被放在头文件中.静态数据成员初始化时不受private和protected访问限制. 注意:不要试图在头文件中定义静态数据成员.在大多数情况下,这样做会引起重复定义这样