C++ friend 用法简单总结

在C++中,friend是破坏封装性的,friend 的在C++语法体系是一个比较小的知识点,在开发中用的也不是很多。friend 的用法有时很容易忘记,一些陷阱经常跳进去。本文做了一个简短总结。

C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。友元包括友元的声明以及友元的定义。友元的声明默认为了extern,就是说友元类或者友元函数的作用域已经扩展到了包含该类定义的作用域,所以即便我们在类的内部定义友元函数也是没有关系的。

1.普通的非成员函数友元

这类友元函数最常见,通常是操作符,例如输入输出操作符,示例如下所示:

//OpeClass.h
#pragma once
class OpeClass
{
	friend OpeClass& operator <<(const OpeClass& xx);
public:
	OpeClass(void);
	OpeClass(int x,int y);
	~OpeClass(void);
private:
	int width;
	int height;
};
//OpeClass.cpp
#include "OpeClass.h"

OpeClass::OpeClass(void)
{
	width = 50;
	height = 50;
}

OpeClass::OpeClass(int x,int y):width(x),height(y)
{
}

OpeClass::~OpeClass(void)
{
}

OpeClass& operator<<(const OpeClass& xx)
{
	cout<<xx.width<<xx.height;
	return *this;
}

2.类作为友元

类作为友元需要注意的是友元类和原始类之间的相互依赖关系,如果在友元类中定义的函数使用到了原始类的私有变量,那么就需要在友元类定义的文件中包含原始类定义的头文件。但是在原始类的定义中(包含友元类声明的那个类),就不需要包含友元类的头文件.

另外,不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明。

//A.h
#pragma once
#include <iostream>
using namespace std;
class A
{
	//friend class B;  //如果不写这句话将会出现编译错误
public:
	~A(void);
	A();
private:
	int m_nItem;
};
//A.cpp
#include "A.h"

A::A()
{
	m_nItem =3;
}

A::~A(void)
{
}
//B.h
#pragma once  

class B
{
public:
	B(void);
	~B(void);
	int func();
};
//B.cpp
#include "StdAfx.h"

#include "B.h"
#include "A.h" //must include A.h
#include <iostream>

B::B(void)
{
}

B::~B(void)
{
}

int B::func()
{
	cout<<"This is in B"<<endl;
	A a;
	return a.m_nItem;
}  

3.类成员函数作为友元函数

这个稍微有点复杂,因为你要类成员函数作为友元,你在声明友元的时候要用类限定符,所以必须先定义包含友元函数的类,但是在定义友元的函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱。(如果是友元类,则没有这种这种必须)如下面所示:

//A.h
#pragma once
#include "B.h"
class A
{
friend int B::func(A xx);
public:
	A(void):mx(20),my(30){}
	~A(void){}
private:
	int mx;
	int my;
};
//B.h
#pragma once
class A;
class B
{
public:
	B(void);
	~B(void);
	int func(A xx);
};
//B.cpp
#include "B.h"
#include "A.h"

B::B(void)
{
}

B::~B(void)
{
}

int B::func(A xx)
{
	return xx.mx * xx.my;
}
//main.cpp
#include "A.h"
#include "B.h"
#include <iostream>
using namespace std;
void main()
{
	A a;
	B b;
	cout<<b.func(a)<<endl;
	system("pause");
}

4. 友元不具有相互性,只具有单项性

若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

5. 友元不能被继承

B是A的友元类,C是B的子类,推不出C是A的友元

6. 友元不具有传递性

B是A的友元,C是B的友元,推不出C是A的友元

7. 友元函数的使用技巧

在用C++实现单例模式时,可以利用友元函数实例化对象。然后把类的构造函数和析构函数都设计成私有函数。

class CMySingleton
{
public:
    friend CMySingleton& InstanceMEC();

private:
    CMySingleton() {};
    CMySingleton(const CMySingleton &lxSington) {};
    ~CMySingleton(){};
};

CMySingleton& InstanceMEC()
{
    //因为函数InstanceMEC()是类ClxSingletonMEC的友元函数,所以可以访问类所有的成员函数.所以不会有编译错误
    static CMySingleton Instance;
    return Instance;
} 







时间: 2024-11-10 07:29:44

C++ friend 用法简单总结的相关文章

CSS3的calc()用法简单介绍

CSS3的calc()用法简单介绍:calc是calculate(计算的意思)缩写.从calc()的外表来看,它类似于程序语言中的方法,具有计算功能.确实如此,它可以动态的计算css中一些元素的相关属性值,能够运用简单的"+"."-"."*"."/"四则运算.基本规则如下:(1).可以使用百分比.px.em.rem等单位.(2).可以混合使用各种单位进行计算.下面看几个代码片段: .box{ border:1px solid

js的nextSibling属性用法简单介绍

js的nextSibling属性用法简单介绍:此属性可以返回当前节点的下一个同级节点.如果下一个同级节点不存在,则此属性返回值是null.语法结构: elementNode.nextSibling 代码实例: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.softw

$.extend()和$.fn.extend()函数用法简单介绍

$.extend()和$.fn.extend()函数用法简单介绍:标题中的两个方法在jQuery插件开发中非常的重要,下面通过简单的代码实例介绍一下它们的用法.本章节不会介绍它的原理,而是只给出它们的作用是什么,能够做什么事情.jQuery.extend()可以为jQuery类添加新的方法,类似于c#或者java中的静态方法.jQuery.fn.extend()可以为jQuery的对象实例添加新的方法.代码实例: <!DOCTYPE html> <html> <head>

getAttribute()用法简单介绍

getAttribute()用法简单介绍:此方法返回指定属性名的属性值.语法结构: element.getAttribute(attributename) 参数解析:attributename:必需,要获得属性值的属性名称. 代码实例: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="h

Unity3d中SendMessage 用法简单笔记

Unity3d中SendMessage 用法简单笔记 Message相关有3条指令:SendMessage ("函数名",参数,SendMessageOptions) //GameObject自身的ScriptBroadcastMessage ("函数名",参数,SendMessageOptions)  //自身和子Object的ScriptSendMessageUpwards ("函数名",参数,SendMessageOptions)  //自

nextSibling属性用法简单介绍

js的nextSibling属性用法简单介绍:此属性可以返回当前节点的下一个同级节点.如果下一个同级节点不存在,则此属性返回值是null.语法结构: elementNode.nextSibling 代码实例: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.softw

Urllib.request用法简单介绍(Python3.3)

Urllib.request用法简单介绍(Python3.3),有需要的朋友可以参考下. urllib是Python标准库的一部分,包含urllib.request,urllib.error,urllib.parse,urlli.robotparser四个子模块,这里主要介绍urllib.request的一些简单用法. 首先是urlopen函数,用于打开一个URL: # -*- coding:utf-8 -*- #获取并打印google首页的htmlimport urllib.requestre

js的table表格对象的rows属性用法简单介绍

js的table表格对象的rows属性用法简单介绍:rows作用正如其拼写一样,是用来获取一个行的集合,也就是表格中行的集合.代码如下: <!DOCTYPE html><html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/" /> <title>蚂蚁部

HTML5的autofocus属性用法简单介绍

HTML5的autofocus属性用法简单介绍: 本章节简单介绍一下HTML5中新增的一个属性autofocus,它可以让一个元素加载后获取焦点,在此之前一般要通过使用javascript的focus()方法实现我们的要求,非常的简单,代码如下: <input type="text" autofocus="autofocus" /> <textarea autofocus="autofocus">蚂蚁部落</text

&lt;iframe&gt;用法简单介绍

<iframe>用法简单介绍:本章节简单介绍一下<iframe>标签的用法,因为当前它在很多效果中都有应用,并且也非常的好用,本站的手机网站模板下载的演示效果就是利用<iframe>实现的,下面简单介绍一下次标签的用法.代码实例如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="author"