一、实验目的和任务
1)熟练掌握友元函数的设计方法;
2)掌握友元函数的含义,友元函数和成员函数的区别;
3)掌握静态数据成员的初始化方法;
4)掌握静态成员函数的定义与使用方法。
二、实验原理介绍
根据要求正确定义友元函数。将别的模块声明为友元,使类中本隐藏的信息如私有和保护成员可以被友元访问。
静态成员属于类的成员,访问类的静态成员可以直接用类名访问,静态数据成员的初始化必须在类外进行,类的静态成员函数访问类的非静态成员函数必须通过类的对象访问。
三、参考代码
1、将一个类的成员函数说明为另一个类的友元函数:类 N 有两个整型私有数据成员 c、d; 一个公有成员函数 Print(),功能为打印输出 N 类的数据成员的值;类 M 有两个整型私有数据 成员 a、b;一个公有成员函数 Print(),功能为打印输出 M 类的数据成员的值,另一个公有成 员函数 Setab(N &)功能为访问 N 类的私有成员,并将 N 的私有成员的值赋给M 类的成员,类的 私有成员是不允许在类外访问的,为了实现 M类的成员函数访问 N 类的私有成员,必须将 Setab 函数声明为 N 类的友元。
#include <iostream>
using namespace std;
class N; // N类的引用性说明,因为N的定义在M之后。而M中又使用了N
class M
{
private:
int a, b;
public:
M(int x, int y) // 类M的构造函数
{
a = x; b = y;
}
void Print()
{
cout << "a=" << a << '\t' << "b=" << b << endl;
}
void Setab(N&); // Setab()是类M的成员函数,带有一个N类的引用的形参
};
class N
{
private:
int c, d;
public:
N(int a, int b) // 类N的构造函数
{
c = a; d = b;
}
void Print()
{
cout << "c=" << c << "\t" << "d=" << d << endl;
}
friend void M::Setab(N&); // 为了Setab函数能访问N类的私有成员,将M类的成员函数说明成N类的友元函数
};
void M::Setab(N& obj) // M的成员函数Setab()是类N的友元函数
{
a = obj.c; // 直接通过N类的对象访问N的私有成员
b = obj.d;
}
void main()
{
M m(25, 40);
N n(55, 66);
cout << "m:"; m.Print();
cout << "n:"; n.Print();
m.Setab(n);
cout << "m:"; m.Print();
}
2、定义一个类,该类的数据成员由一个整型成员 a 和整型静态成员 b 组成,静态成员初始化值为 10,静态成员函数 disp 用于输出数据成员的值。主函数中分别构造两个该类的对象,通过静态成员函数输出类的数据成员的值,观察在不同的对象中静态数据成员的变化
#include <iostream>
using namespace std;
class Sample
{
int a;
static int b; // 静态数据成员
public:
Sample(int x) // 构造函数
{
a = x;
b += x;
}
static void disp(Sample s) // 静态成员函数只能访问静态数据成员,非静态成员需要通过对象访问
{
cout << "a=" << s.a // 非静态数据成员通过类的对象访问
<< ",b=" << b << endl; // 静态数据成员直接访问
}
};
int Sample::b = 10; // 静态数据成员在类外赋初值
void main()
{
Sample s1(12);
Sample::disp(s1); // s1.disp(s1); // 静态成员函数直接通过类访问。成员 ? 12 22 (两种表达方式均可)
Sample s2(3);
Sample::disp(s1); // s1.disp(s1); // 成员b ? 12 25 (两种表达方式均可)
Sample::disp(s2); // s2.disp(s2); // 成员b ? 3 25 (两种表达方式均可)
}