1.概述:
有的时候类需要它的一些成员与类本身直接相关,而不是与类的各个对象保持关联。
2.实例:
ClassStaticMember.h
namespace NameSpaceForTest
{
class SimpleClassForTest
{
public:
SimpleClassForTest();
~SimpleClassForTest();
static int StaticFunc();
int NonStaticFunc();
private:
static int _StaticFunc();
private:
int m_nVal;
static int sm_nVal;
};
}
ClassStaticMember.cpp
namespace NameSpaceForTest
{
int SimpleClassForTest::sm_nVal = 0;
SimpleClassForTest::SimpleClassForTest()
{
m_nVal = 0;
}
SimpleClassForTest::~SimpleClassForTest()
{
}
int SimpleClassForTest::StaticFunc()
{
return ++sm_nVal;
}
int SimpleClassForTest::NonStaticFunc()
{
sm_nVal = _StaticFunc() + 1;
return ++m_nVal;
}
int SimpleClassForTest::_StaticFunc()
{
return sm_nVal;
}
}
main.cpp
#include <iostream>
#include "ClassStaticMember.h"
int main()
{
NameSpaceForTest::SimpleClassForTest mySimpleClassForTest;
NameSpaceForTest::SimpleClassForTest& rSimpleClassForTest = mySimpleClassForTest;
NameSpaceForTest::SimpleClassForTest* pSimpleClassForTest = &mySimpleClassForTest;
std::cout<<mySimpleClassForTest.NonStaticFunc()<<std::endl;
std::cout<<mySimpleClassForTest.StaticFunc()<<std::endl;
std::cout<<NameSpaceForTest::SimpleClassForTest::StaticFunc()<<std::endl;
std::cout<<rSimpleClassForTest.StaticFunc()<<std::endl;
std::cout<<pSimpleClassForTest->StaticFunc()<<std::endl;
return 0;
}
输出
1
2
3
4
5
3.说明:
3.1声明静态成员
我们通过在成员的声明之前加上关键字static使其与类关联在一起。和其他成员一样,静态成员可以是public的或private的。静态数据成员的类型可以是常量、变量、引用、指针、类类型等:
class SimpleClassForTest
{
public:
SimpleClassForTest();
~SimpleClassForTest();
static int StaticFunc();
int NonStaticFunc();
private:
static int _StaticFunc();
private:
int m_nVal;
static int sm_nVal;
};
(1)类的静态成员存在与任何于对象之外,对象中不包括任何与静态数据成员有关的数据。
(2)类似的,静态成员函数也不与任何对象绑定在一起,它们不包含this指针。作为结果,静态成员函数不能声明成const,而且我们也不能在static函数体内使用this指针。这一限制既适用于指针的显示使用,也对调用非静态成员的隐式使用有效。
3.2定义静态成员
(1)和其他的成员函数一样,我们既可以在类的内部也可以在类的外部定义静态成员函数。当在类的外部定义静态成员时,不能重复static关键字,该关键字只能出现在类内部语句的声明:
int SimpleClassForTest::StaticFunc()
{
return ++sm_nVal;
}
(2)因为静态数据成员不属于类的任何一个对象,所以它们并不是在创建里的对象时被定义的。这意味着它们不是由类的构造函数初始化。而且一般来说,我们不能在类的内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,一个静态数据成员只能被定义一次。
类似于全局变量,静态数据成员定义在任何函数之外。因此一旦它被定义,就将一直存在程序的整个生命周期中。
我们定义静态数据成员的方式和类的外部定义成员函数差不多。我们需要指定对象的类型名,然后是类名、作用域运算符以及成员自己的名字:
int SimpleClassForTest::sm_nVal = 0;
3.3使用类的静态成员
(1)我们使用作用域运算符直接访问静态成员:
NameSpaceForTest::SimpleClassForTest::StaticFunc();
(2)虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象、引用或者指针来访问静态成员:
mySimpleClassForTest.StaticFunc();
rSimpleClassForTest.StaticFunc();
pSimpleClassForTest->StaticFunc();
(3)成员函数不用通过作用域就能直接使用静态成员:
int SimpleClassForTest::NonStaticFunc()
{
sm_nVal = _StaticFunc() + 1;
return ++m_nVal;
}
//这里包括数据成员和函数成员。
(4)静态函数成员不能调用非静态成员包括:非静态数据成员和函数成员。
3.4静态成员的类内初始化
略。
3.5静态成员能用于某些场景,而普通成员不能
静态成员独立于任何对象。因此,在某些非静态数据成员可能非法的场合,静态成员却可以正常地使用。
(1)静态数据成员的类型可以就是它所属的类类型。而非静态数据成员则受到限制,只能声明成他所属类的指针或引用。
class Bar
{
public:
//...
private:
static Bar mem1; // 正确
Bar* mem2; // 正确
Bar mem3; // 错误
}
(2)静态成员和普通成员的另外一个区别是我们可以使用静态成员作为默认实参。
class Screen
{
public:
Screen& clear(char = bkground);
private:
static const char bkground;
}