C++之友元函数

目录

1.定义:

1.概念:

2.注意

3.友元的分类:

4.友元函数代码分析:

1.友元函数出现的原因(外部函数友元为例):

2.一个外部函数作为多个类的友元函数

3.成员函数友元:

4.类友元:

5.特点:

1.不具有对称性 :

2.不具有传递性 :

3.不具有继承性:

6.总结:

1.友元函数不是类的成员函数。

2.友元函数不受类中的访问权限关键字限制。

3.某类的友元函数的作用域并非该类作用域。


1.定义:

1.概念:

友元 friend 机制允许一个类授权其他的函数访问它的非公有成员。友元声明以关键字 friend 开头 ,它只能出现在类的声明中, 它们不受其在类体中的 public private 和 protected 区的影响.。

通俗来说就是就是让函数或者类作为另外一个类的朋友,则可以访问当前类的private或者protected类。

2.注意

1.一个普通函数作为类的友元,那么在当前函数中就可以通过对象访问类的私有或者保护成员
  注意:这个函数只能在外部定义,在当前类中引用即可
2.一个类的成员函数作为另外一个类的友元
  注意:成员函数建议放在类外定义
3.一个类A作为另外一个类B的友元类,则A的所有的成员函数就可以访问B的私有数据成员或者保护

3.友元的分类:

友元分为外部函数友元, 成员函数友元,类友元。

4.友元函数代码分析:

1.友元函数出现的原因(外部函数友元为例):

class A
{
public:
	A(int i=0):m_i(i){}
private:
	int m_i;
};

void main()
{
	A a(5);
	A b(8);
	Add(a, b);
}
想在Add函数中访问私有数据成员,在之前我们通过接口实现了Add函数,那如果不想通过接口(共有函数),我们可以怎么实现呢?
class A
{
public:
	A(int i=0):m_i(i){}
	int GetI()const
	{
		return m_i;
	}
	friend void Add(A& a, A& b);//将Add函数作为类A的友元,在类外部定义,(不能在类A中定义)
protected:
	//friend void Add(A& a, A& b);
private:
	int m_i;
	//friend void Add(A& a, A& b);
};

//想在Add函数中访问私有数据成员,又不想通过接口(公有函数)
void Add(A& a, A& b)
{
	cout << a.m_i + b.m_i << endl;
	//cout << a.GetI() + b.GetI() << endl;//接口
}
void main()
{
	A a(5);
	A b(8);
	Add(a, b);
}

402be56990684a89a4283e6656db125f.png

分析:

1.在类A的外部写入了一个公有函数

2.在类A中写入friend void Add(A& a, A& b);即就是将Add函数作为类A的友元,

注意该函数只能在类A的外部定义

3.即A可以访问Add函数,对a,b进行求和。

该例子为外部函数友元

2.一个外部函数作为多个类的友元函数

那如果一个外部函数作为多个类的友元函数,代码是完全一样的吗?

不完全一样,需要前向引用声明。

class B;//前向引用声明
class C;
class A
{
public:
	A(int i = 0) :m_i(i) {}
	friend int Sum(A& a, B& b, C& c);
private:
	int m_i;
};
class B
{
public:
	B(int j = 0) :m_j(j) {}
	friend int Sum(A& a, B& b,C& c);
private:
	int m_j;
};
class C
{
public:
	C(int k = 0) :m_k(k) {}
	friend int Sum(A& a, B& b,C&c);
private:
	int m_k;
};
int Sum(A& a, B& b,C&c)
{
	return a.m_i + b.m_j+c.m_k;
}
void main()
{
	A a(10);
	B b(20);
	C c(30);
	cout << Sum(a, b, c) << endl;
}

0a9c441b79144cc7bdc1861840b0c5cc.png

分析:

1.在类A、B、C的外部写入了一个公有函数Sum

2.在类A、B、C中均写入friend void Add(A& a, A& b);即就是将Add函数作为类A的友元,

顺序不是第一个的类必须向前引用声明, 否则会出现以下错误:

47d3a5038f414627834fafc0f3abdc29.png

3.成员函数友元:

有若干不同的类,究竟哪个应该放在首个,哪些向前引用声明呢?

class C;
class A;
class B
{
public:
	B(int j = 0) :m_j(j) {}
	void Sub(A& a, B& b, C& c);
	void Print(A& a);
private:
	int m_j;
};
class A
{
public:
	A(int i = 0) :m_i(i) {}
	friend void B::Sub(A& a, B& b, C& c);
	friend void B::Print(A&a);
private:
	int m_i;
};
class C
{
public:
	C(int k = 0) :m_k(k) {}
	friend void B::Sub(A& a, B& b, C& c);
private:
	int m_k;
};
void B::Sub(A& a,B&b,C&c)
{
	cout << a.m_i - m_j +c.m_k<< endl;
}
void B::Print(A&a)
{
	cout << a.m_i << endl;
}
void main()
{
	A a(10);
	B b(20);
	C c(30);
	b.Sub(a,b,c);
	b.Print(a);
}
分析: 一般情况下,把声明函数的类放在前面,函数的定义写在类的外面 aee82934688b4ba29031b2d5ec5f566a.png

class A
{
public:
	A(int i = 0) :m_i(i) {}
	friend void B::Sub(A& a, B& b, C& c);
	friend void B::Print(A&a);
private:
	int m_i;
}

在这段代码中类B的成员函数Sub、Print都作为了类A的友元

4.类友元:

class B;
class A
{
public:
	A(int a = 0) :m_a(a) {}
	void print(B& b);
	void test(B& b);
	void show(B& b);
private:
	int m_a;
};
class B
{
public:
	B(int b=0):m_b(b){}
	friend class A;
private:
	int m_b;
};

void A::print(B& b)
{
	cout << "a::print:" << b.m_b << endl;
}
void A::test(B& b)
{
	cout << "a::test:" << b.m_b << endl;
}
void A::show(B& b)
{
	cout << "a::show:" << b.m_b << endl;
}
void main()
{
	A a(2);
	B b(10);
	a.print(b);
	a.show(b);
	a.test(b);
}

类A作为类B的友元函数,(在B中写friend class A的意思就是:告诉B,A是它的friend),所以类A可以访问类B中的所有函数,只需在类A中声明。

e28d7a00809e4fafb832f4f2f6ece81c.png

A、B两类也可以互为友元类

class B;
class A
{
public:
	A(int a = 0) :m_a(a) {}
	void print(B& b);
	void test(B& b);
	void show(B& b);
	friend class B;
private:
	int m_a;
};
class B
{
public:
	B(int b=0):m_b(b){}
	friend class A;
	void Print(A& a);
private:
	int m_b;
};
void B::Print(A& a)
{
	cout << a.m_a << endl;
}
void A::print(B& b)
{
	cout << "a::print:" << b.m_b << endl;
}
void A::test(B& b)
{
	cout << "a::test:" << b.m_b << endl;
}
void A::show(B& b)
{
	cout << "a::show:" << b.m_b << endl;
}
void main()
{
	A a(2);
	B b(10);
	a.print(b);
	a.show(b);
	a.test(b);
	b.Print(a);
}

6ce5b4787abb49639abe7e2f9c433002.png

A、B互为友元类,即就是,只要声明了,就可以访问友元类的成员函数。 

5.特点:

1.不具有对称性 :

A 是 B 的友元, 并不意味着 B 是A的友元。

class B;
class A
{
public:
	A(int a = 0) :m_a(a) {}
	void print(B& b);
	void test(B& b);
	void show(B& b);
private:
	int m_a;
};
class B
{
public:
	B(int b=0):m_b(b){}
	friend class A;
	void Print(A& a);
private:
	int m_b;
};
void B::Print(A& a)
{
	cout << a.m_a << endl;
}
void A::print(B& b)
{
	cout << "a::print:" << b.m_b << endl;
}
void A::test(B& b)
{
	cout << "a::test:" << b.m_b << endl;
}
void A::show(B& b)
{
	cout << "a::show:" << b.m_b << endl;
}
void main()
{
	A a(2);
	B b(10);
	a.print(b);
	a.show(b);
	a.test(b);
	b.Print(a);
}

fc08dde90f1647bf968af44c880f209f.png

 没有告诉A:B是它的朋友,所以B不能访问A 的私有成员

2.不具有传递性 :

A是B的友元, B是C的友元, 但A不是C的友元。

class AA
{
public:
	friend class BB;
private:
	int m_a;
};
class BB
{
public:
	friend class CC;
	void Show(AA& a);
private:
	int m_b;
};
class CC
{
public:
	void printf(BB& b);
	void test(AA& a);
};
void BB::Show(AA& a)
{
	cout << a.m_a << endl;
}
void CC::printf(BB& b)
{
	cout << b.m_b << endl;
}
void CC::test(AA& a)//友元是不能进行传递的
{
	//cout << a.m_a << endl;//error
}
void main()
{
	AA a;
	BB b;
	CC c;
	b.Show(a);
	c.printf(b);
	c.test(a);//error
}
void CC::test(AA& a)//友元是不能进行传递的
{
    //cout << a.m_a << endl;//error
}
* BB是AA 的朋友
* CC是BB 的朋友
//CC不是AA的朋友,不能访问AA的数据成员 8f2e75d0531d44248e0e2314abf8e096.png

3.不具有继承性:

Base 类型继承 Object类型, 如果Object 类型是A的友元,但Base类型不是A友 元。

6.总结:

1.友元函数不是类的成员函数。

在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员 名。但友元函数可以访问类中的所有成员,一般函数只能访问类中的公有成员。

2.友元函数不受类中的访问权限关键字限制。

可以把它放在类的公有、私有、保护部分,但结果一 样。

3.某类的友元函数的作用域并非该类作用域。

如果该友元函数是另一类的成员函数,则其作用域为 另一类的作用域,否则与一般函数相同。

  • 80
    点赞
  • 274
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值