C++友元关系和类的静态成员概念和使用

原创 2012年03月24日 18:34:16

一: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

#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;
	 
}
运行结果截图:




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

java中String s="abc"及String s=new String("abc")详解

1.   栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。  2.   栈的优势是,存取速度比堆要快,...

NULL指针能在赋值吗

指针在使用前要进行初始化,我将指针初始化为NULL,再对它赋值,为啥不行呢? #include void main() { int *a = NULL; *a = 3; printf("%d",*a)...

C++:内嵌类、静态成员变量和函数、单例模式、友元函数和友元类

一、内嵌类 1. 什么是内嵌类: 内嵌类是指,一个类定义在另一个类的内部。 2. 类内声明,类外实现的方法: 返回类型 外部类::内嵌类::函数名(形参表) {...} /** 代码演示 *...

C++知识文档六_对象常量_静态成员_友元_抽象类

对象和常量   常对象。常对象指在任何场合都不能对其成员的值进行修改的对象。 定义常对象的形式为: const类名 对象名(参数列表); 或者 类名 const 对象名(参数列表);   ...

C++ Day04静态成员,友元,面向对象模型

&&静态成员 在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static声明为静态的,称为静态成员。 不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个...

C++静态成员与友元

静态成员是指声明为static的类的成员在类的范围内所有对象共享某个数据。友元是一种定义在类外部的普通函数,但它需要在类的内部进行说明,为了与该类的成员函数加以区别,在说明时前面加上关键字friend...

二十五、继承(二) 不能自动继承的成员函数、继承与构造函数、友元关系与继承、静态成员与继承

一、不能自动继承的成员函数           有三种函数不能被继承,构造函数,析构函数和=运算符,基类的构造函数和析构函数只负责对基类数据成员的初始化和清理,因为基类并不知道派生类有哪些数据成员。=...

对象的赋值与复制,静态成员 友元 类模板

一、对象的赋值和复制 1、对象的赋值 如果对一个类定义了两个或多个对象,则这些同类的对象之间可以互相赋值,或者说,一个对象的值可以赋给另一个同类的对象。这里所指的对象的值是指对象中所有数据成员的值...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)