同类对象间通过静态成员(静态数据成员和静态成员函数)实现数据的共享
一、静态成员
静态成员可以在同一个类的不同对象之间提供数据和函数的共享,无论该类创建了多少个对象,静态成员只有一份拷贝,为所有属于这个类的对象所共享。
1、静态数据成员(同类对象之间进行数据交流)
静态数据成员是解决一个类的不同对象之间的数据共享问题,同一类的所有对象共享此成员,该成员只有一份拷贝。静态数据成员的声明格式如下:
static 类型名 静态数据成员名
该静态成员在该类的任何对象被创建前就已经存在了,所以其初始化工作不能通过类的构造函数来完成,而必须在类定义结束之后进行,其默认为0,静态数据成员是在编译时创建并初始化的。
公有的静态数据成员可以在对象定义之前被访问,格式如下:
类名::公有静态成员变量名
定义对象后也可通过对象进行访问:
对象名.公有静态成员变量名
私有的静态数据成员不能被类外的函数访问,也不能用对象名直接访问,而需要通过对象调用操作该静态数据成员的公有成员函数进行。
静态数据成员的初始化示例如下:
class A
{
int a;
public:
static int s;//公有的静态数据成员
void FuncA(...);
};
A::s = S;
2、静态成员函数
如果静态数据成员是私有的,此时就需要借助于类的公有成员函数来访问。因为静态数据成员不属于任何类,所以访问的成员函数也应该不依赖于任何类,这就是静态成员函数,静态成员函数在类中的原型声明形式:
static 返回值类型 静态成员函数名(形式参数表)
静态成员函数在类的范围内共享,它属于该类的所有对象,只能直接访问静态数据成员,不能对类的其它类型的数据成员或成员函数进行访问。可以通过类名或对象名进行访问:
类名::静态成员函数名(实际参数表) 或 对象名.静态成员函数名(实际参数表)
私有静态数据成员也要在类外,对象定义之前以下面格式初始化:
类名::私有静态数据成员 = 初始化值
注意:静态成员函数没有指针,它几乎是专门为方便操作静态数据成员而设的,所以一般不用来访问非静态成员。
二、共享数据的保护
数据的共享必定带来安全隐患,C++通过适时地巧用关键字const来解决数据共享和数据安全的同一问题。
1、常数据成员
类内的某一数据成员是不能被修改的。
定义格式如下:
const 类型名 常数据成员名
注意:常数据成员的初始化只能在构造函数的初始化表中进行,不能在构造函数的函数体中用赋值等语句实现,而普通的数据成员两种方式都可以。
初始化列表的形式:
构造函数首部:常数据成员名(用来初始化的常量或常量表达式)
例:
class A
{
const int v;
int u;
public:
A(int x):v(C)
{
u = x;
}
};
上例中的常数据成员是跟着对象走的,即同一个常数有多个拷贝,而通常整个类只需要一个常数就可以了,所以一般将常数据成员定义为静态常数据成员,即:
static const 类型名 静态常数据成员名
静态常数据成员的初始化不可以在初始化列表中完成,与静态数据成员类似,要在类定义结束后单独初始化。对于多文件结构,该初始化一定不能放在头文件中。
2、常成员函数
一个成员函数对类中的数据成员只作访问不作直接或间接的修改时,最好将其说明为常成员函数,以表明其对数据成员的保护性。常成员函数原型格式:
类型 函数名(形参列表) const;
const是函数类型的一个组成部分,在常成员函数的原型声明及函数定义时都要使用关键字const。且关键字const可以作为与其它成员函数重载的标志,如void Print() const;和void Print();都是正确的重载函数。
注意:常成员函数不能调用未经const修饰的普通函数(普通函数可以修改数据成员的值),但反过来可以被调用。
3、常对象
对象的整个生存期内都不能被改变时,可将其说明为常对象,格式如下:
类名 const 对象名 或 const 类名 对象名
在定义常对象时同样必须进行初始化,且其数据成员值不能修改,常对象只能调用它的常成员函数而不能调用它的普通成员函数(因为常对象的所有数据成员值不能被修改)。
注意:在调用重载函数时,常对象一定调用的是常成员函数,普通对象遵循这样的原则:如果有普通成员函数的重载版本,则首先调用普通的成员函数,否则自动调用常成员函数。