C++程序设计 湖南大学 杜四春、银红霞
第 10章 静态成员与友元
10.1 静态成员
10.2 友元
10.3 友元应用实例
C++程序设计 湖南大学 杜四春、银红霞
静态成员是指声明为 static的类成员在类的
范围内所有对象共享某个数据。友元是一种定
义在类外部的普通函数,但它需要在类的内部
进行说明,为了与该类的成员函数加以区别,
在说明时前面加上关键字 friend。友元不是成
员函数,但它可以访问类中的私有成员。其作
用是提高程序的运行效率。 C++语言中的友元
函数为在类外访问类中的私有成员和保护成员
提供了方便,但破坏了类的封装性和隐蔽性。
友元可以是一个函数,称为友元函数,也可以
是一个类,称为友元类。友元函数和友元类统
称为友元。
C++程序设计 湖南大学 杜四春、银红霞
10.1 静态成员
类相当于一个数据类型,当说明一个某类
的对象时,系统就为该对象分配一块内存单元
来存放类中的所有成员。但在某些应用中,需
要程序中属于某个类的所有对象共享某个数据。
为此,一个解决的办法就是将所要共享的数据
说明为全局变量,但这将破坏数据的封装性;
较好的解决办法是将所要共享的数据说明为类
的静态成员。
C++程序设计 湖南大学 杜四春、银红霞
10.1.1 静态数据成员
C++中, 同一个类定义多个对象时, 每个对象拥
有各自的数据成员 ( 不包括静态数据成员 ), 而所有
对象共享一份成员函数和一份静态数据成员 。 静态数
据成员是类的所有对象中共享的成员, 而不是某个对
象的成员, 因此可以实现多个对象间的数据共享 。 静
态数据成员不属于任何对象, 它不因对象的建立而产
生, 也不因对象的析构而删除, 它是类定义的一部分,
所以使用静态数据成员不会破坏类的隐蔽性 。
对静态数据成员的操作和一般数据成员一样, 定
义为私有的静态数据成员不能由外界访问 。 静态数据
成员可由任意访问权限许可的函数访问 。 可以在类的
成员函数中改变静态数据成员 。
C++程序设计 湖南大学 杜四春、银红霞
静态数据成员不从属于任何一个具体对象, 所以
必须对它初始化, 且对它的初始化不能在构造函数中
进行 。 类中用关键字 static修饰的数据成员叫做静态数
据成员 。 说明一个静态数据成员的方法与说明一个一
般静态变量一样, 只不过前者是在一个类中说明 。
静态数据成员的使用方法如下:
( 1) 静态数据成员的定义与一般数据成员相似,
但前面要加上 static关键词 。
( 2) 静态数据成员的初始化与一般数据成员不同,
静态数据成员初始化的格式如下:
<类型 ><类名 >::<静态数据成员 >=<值 >;
( 3) 在引用静态数据成员时采用格式:
<类名 >::<静态数据成员 >
C++程序设计 湖南大学 杜四春、银红霞
class Class1
{ int a;
static int b;
//…
}c1,c2;
int Class1::b;
类 Class1中包含两个数据成员 a和 b,其中 a为一般
数据成员,在对象 c1和 c2中都存在有各自的该数据成
员的副本;而 b是静态数据成员,所有类 Class1的对象
中的该成员实际上是同一个变量。 C++编译器将静态
数据成员存放在静态存储区,该存储区中的所有数据
为类的所有对象所共享。
C++程序设计 湖南大学 杜四春、银红霞
10.1.2 静态成员函数
静态成员函数的定义和其他成员函数一样 。 但在
说明时需注意静态成员函数不得说明为虚函数 。 静态
成员函数与静态数据成员类似, 也是从属于类, 静态
成员函数的定义是在一般函数定义前加上 static关键字 。
调用静态成员函数的格式如下:
<类名 >::<静态成员函数名 >( <参数表 >) ;
静态成员函数与静态数据成员一样,与类相联系,
不与对象相联系,只要类存在,静态成员函数就可以
使用,所以访问静态成员函数时不需要对象。如果用
对象去调用静态成员函数,只是用其类型。
C++程序设计 湖南大学 杜四春、银红霞
静态成员函数只能访问静态数据成员, 静态成员
函数和类以外的函数和数据, 不能访问类中的非静态
数据成员 ( 因为非静态数据成员只有对象存在时才有
意义 ) 。 但静态数据成员和静态成员函数可由任意访
问权限许可的函数访问 。 和一般成员函数类似, 静态
成员函数也有访问限制, 私有静态成员函数不能由外
界访问 。
静态成员函数没有 this指针,因此,静态成员函数
只能直接访问类中的静态成员,若要访问类中的非静
态成员时,必须借助对象名或指向对象的指针。
C++程序设计 湖南大学 杜四春、银红霞
10.2 友元
友元提供了在不同类的成员函数之间, 类
的成员函数与一般函数之间进行数据共享的机
制 。 通过友元, 一个普通函数或另一个类中的
成员函数可以访问类中的私有成员和保护成员 。
友元的正确使用能提高程序的运行效率, 但破
坏了类的封装性和数据的隐蔽性 。
10.2.1 友元函数
定义友元函数的方式是在类定义中用关键词 friend
说明该函数, 其格式如下:
friend <类型 > <友元函数名 >( <参数表 >) ;
C++程序设计 湖南大学 杜四春、银红霞
友元函数说明的位置可在类的任何部位, 既可在
public区, 也可在 protected区, 意义完全一样 。 友元函
数定义则在类的外部, 一般与类的成员函数定义放在
一起 。
类的友元函数可以直接访问该类的所有成员,但
它不是成员函数,可以像普通函数一样在任何地方调
用。友员函数的定义方法是在类的任何地方象定义其
他函数一样定义该函数,并在其前面加上关键字 friend即
可。 友员函数虽然在类内定义,但它不是这个类的成
员函数,它可以是一个普通函数,也可以是其他类的
成员函数,在其函数体中通过对象名访问这个类的私
有或保护成员。
C++程序设计 湖南大学 杜四春、银红霞
10.2.2 友元类
C++允许说明一个类为另一个类的友元类 ( friend
class) 。
如果 A是 B的友员类, 则 A中的所有成员函数可以
像友员函数一样访问 B类中的所有成员 。 定义格式如下:
class B
{ friend class A; //A的所有成员函数均为 B的友员函数
//…
}
C++程序设计 湖南大学 杜四春、银红霞
友元关系不可以被继承 。 假设类 A是类 B的友元,
而类 C从类 B派生, 如果没有在类 C中显式地使用下面
的语句:
friend class A;
那么, 尽管类 A是类 B的友元, 但这种关系不会被
继承到类 C,也就是说, 类 C和类 A没有友元关系, 类 A
的成员函数不可以直接访问类 C的受保护成员和私有成
员 。
不存在“友元的友元”这种关系。假设类 A是类 B
的友元,而类 B是类 C的友元,即是说类 B的成员函数
可以访问类 C的受保护成员和私有成员,而类 A的成员
函数可以访问类 B的受保护成员和私有成员;但是,类
A的成员函数不可以直接访问类 C的受保护成员和私有
成员,即是说友元关系不存在传递性。
C++程序设计 湖南大学 杜四春、银红霞
10.3 友元应用实例
例 10-8:求两数的平方差 。
#include <iostream.h>
class Myclass
{
private:
int a,b,max,min;
public:
Myclass(int i,int j):a(i),b(j)
{
max=(a>b)?a:b;
min=(a<b)?a:b;
}
friend int Result(Myclass& x);
};
int Result(Myclass& x)
{
return=x.max*x.max-x.min*x.min;
}
void main()
{ Myclass n(3,4);
Cout<<Result(n)<<endl; }
此程序的运行结果为:
7