一:C++友元关系:
1.类对于成员的封装(public, private, protected)
1).封装性的优势:
有效地保护了对象的内部细节,使得对象的使用和对象的实现分开,互相不产生影响。
2).封装性的缺陷:
1、C++为实现对象的封装,必然会做一些额外的工作,从而导致程序的效率下降。
(调用成员函数来访问成员的时间开销降低了程序的执行效率)
2、一个对象封装的太好,也会让该对象很难使用,也很难实现。
3).封装性缺陷的弥补:
C++提供了友元(friend)来解决由封装性带来的问题。
friend修饰使其为有友元函数或友元类,其应用于比较特殊的情况(如提高效率),不提倡过度使用。
2.友元关系的分类:
一个类可以声明一个友元关系,一起来共享类中的所有成员。
1.友元类:友元是一个类.
在类中可把另一个类声明为友元类,如类B是类A的友元类,则类B中的所有成员函数都是类A的友元函数,都可以访问类A的私有和保护成员。
2.友元函数:是在类中由关键字friend修饰的非成员函数。
3友元函数的特点:
第一、友元函数可以直接通过对象名访问类的私有和保护成员,可以像普通函数一样在任何地方调用。
不是该类的成员函数,可以是一个普通的函数,也可以是其他类的成员函数。
(朋友虽然不是家庭的成员,但容许到我们家里访问一样)
第二、友元函数不属于任何类,因此可以放在类说明的任何位置,既可以在public区,也可以在private区。
(友元函数看看作是类的部分接口,建议出现在public的部分)
第三、友元函数不需要通过对象或对象指针来调用,可以直接调用即可。
4.友元函数的缺点:
第一:使用友元波坏了封装性,降低了程序的可读性,因此应酌情使用.
第二:友元函数中没有this指针(非类的成员函数),故必须通过函数参数来传递对象.
实例:
//类声明文件:sclass2_16.h
#ifndef __SCLASS2_16_H__
#define __SCLASS2_16_H__
#include<iostream>
using namespace std;
class CSample1
{
public:
CSample1( void ){ }; //空构造函数
//将类CSample2声明为类CSample1的友元类(friend class),相当于类CSample2的所有成员函数都是类CSample1的友元函数,即可以访问其所有成员.
friend class CSample2;
void SetI(int t)
{
i = t;
}
int MemberFunc( void ) //成员函数
{
return i;
}
//友元函数直接访问CSample类的私有数据成员i,即一个类可以声明一个友元关系,一起来共享类中的所有成员
friend void FriendFunc ( CSample1 * cp, int a ) //增加一个对象指针参数
{
cp->i = a; //对象指针参数为i指明当前所属对象
}
private:
int i;
};
class CSample2
{
public:
CSample2( void ) {}
void ShowCSample1()
{
CSample1 ss1;
ss1.SetI(4);
cout << "ss1.i=" << ss1.i << endl;
}
void ShowCSample1(CSample1 s1)
{
cout << "s1.i=" << s1.i << endl;
}
private:
};
#include"sclass2_16.h"
void main( void )
{
CSample1 s1;
s1.SetI(1);
CSample1 *p1 = new CSample1; //创建一个对象指针并初始化
//友元函数不需要通过对象或对象指针来调用,可以直接调用即可。
FriendFunc(p1, 2); //p指针所指的对象的i被赋值为2
cout << "i=" << p1->MemberFunc()<<endl;
delete p1; //释放指针p1
CSample2 s2;
s2.ShowCSample1();
s2.ShowCSample1(s1);
//cout << "s1.i=" << s1.i << endl;
}
二:类的静态数据成员:
1.类的静态成员存在的必要性:
为对象提供了一个相互通信的方法
2.类的静态成员的特点:
类的静态static成员拥有一块单独的存储区,与具体的对象没有关系,只属于类,该类的所有对象都共享这块静态存储空间.
3.类的静态成员的分类:
1).类的静态数据成员:
概念:数据成员名声明的时候加关建字statis,可以用于对象间的数据共享.
定义格式: static int s_iCount; (类内定义)
初始化: int CCompanyStaff::s_iCount = 1001; (类外初始化)
访问方式: CCompanyStaff::s_iCount (在所属类中直接使用) 或者 对象名.变量名.
特点:
类的静态数据成员不可以在类内进行初始化(因其不属于某个对象,否则没创建一个对象其就会被初始化一次,失去了对象间数据共享的意义).
类的静态数据成员可以通过对象名来访问(因其被所有同类的对象共有).
类的静态数据成员可以起到全局变量的作用.可以用于对象间的数据共享.但其优于全局变量:
静态数据成员可以受private,protected修饰,实现信息的隐藏.而全局变量不行.
静态数据成员名不进入全局命名空间,不存在与其他全局变量名冲突的问题.
2).类的静态成员函数:
概念:成员函数声明的时候加关建字statis,它的作用主要是访问和操作同类中的静态数据成员.
特点:
类的静态成员函数主要使用类的静态数据成员,静态成员函数一般不访问普通数据成员.
静态成员函数是是类的非成员函数,它属于整个类,也为同类中所有对象共同拥有。
静态成员函数没有this指针,所以必须通过传递对象引用来实现对其非静态成员的访问.同友元函数
访问对象的成员的情形相同.而且即使没有两者都没有this指针指明当前的所属对象,但可以通过类名或对
象名来实现对它的访问。
访问方式:
类名::函数名() 或者 对象名.函数名() 两种方式.
4.类的静态成员的案例代码:
头文件--类声明文件:sclass2_15.h
[cpp] view plaincopyprint?
#ifndef __SCLASS2_15_H__
#define __SCLASS2_15_H__
#include<iostream> //包含头文件。使用iostream库
using namespace std; //使用std名字空间
class CDemo
{
public:
CDemo( int i=0 ):m_i(i)
{
j = m_i;
}
//定义一个静态成员函数实现对静态数据成员j的操作
static int incr(CDemo &cdemo)
{
return ++j;
cdemo.m_i++;
}
//静态数据成员的定义
static int j;
private:
int m_i;
};
//静态数据成员的初始化
int CDemo::j = 0;
#endif //结束编译预处理
主文件:smain2_15.cpp
#include"sclass2_15.h" //包含类声明文件
void main( void )
{
CDemo cdemo;
cout<<endl;
cout<<"类的静态数据成员的访问"<<endl;
CDemo::j = 1;
cout<<"CDemo::j = "<<CDemo::j<<endl;\
cout<<endl;
cout<<"静态成员函数的访问1:类名::函数名()"<<endl;
cout << "CDemo::incr(cdemo) = " << CDemo::incr(cdemo) << endl;
cout<<endl;
cout<<"静态成员函数的访问2:对象名.函数名()"<<endl;
cout<<"cdemo.incr(cdemo) = "<<cdemo.incr(cdemo)<<endl;
}