C++友元函数

这篇具有很好参考价值的文章主要介绍了C++友元函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

友元——让函数或者类作为另外一个类的朋友,则可以访问当前类的private或者protected

友元friend机制允许一个类授权其他的函数访问它的非公有成员

友元声明以关键字friend开头,它只能出现在类的声明中,它们不受其在类体中的public、private和protected区的影响

一、友元函数可分为以下三种类型:

1、外部函数友元

一个普通函数作为类的友元,那么在当前函数中就可以通过对象访问类的私有或者保护成员

注意:这个函数只能在外部定义,在当前类中引用即可

class A
{
public:
	A(int i=0):m_i(i){}
	int GetI()const
	{
		return m_i;
	}
	friend void Add(A& a, A& b);
protected:
	//friend void Add(A& a, A& b);//将Add函数作为类A的友元,在内部并不能定义
private:
	//friend void Add(A& a, A& b);//在保护和私有都能正确运行
	int m_i;
};

//想在Add函数中访问私有数据成员,又不想通过接口(共有函数)
void Add(A& a, A& b)
{
	cout << a.m_i << endl;
	cout << b.m_i << endl;
	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);
}

函数不止能作为一个类的友元

class B;//前向引用声明
class A
{
public:
	A(int i=0):m_i(i){}
	friend int Sum(A& a, B& b);//在这之前未定义class B,需进行声明
private:
	int m_i;
};
class B
{
public:
	B(int j = 0) :m_j(j) {}
	friend int Sum(A& a, B& b);//一般情况下放在共有里面
private:
	int m_j;
};
int Sum(A& a, B& b)
{
	return a.m_i + b.m_j;
}
void main()
{
	A a(20);
	B b(20);
	cout << Sum(a, b) << endl;
}

2、成员函数友元

一个类的成员函数作为另一个类的友元

注意:成员函数建议放在类外定义

class A;
class B
{
public:
	B(int j = 0) :m_j(j) {}
	void  Sub(A& a);
	void Print(A& a);
private:
	int m_j;
};
class A
{
public:
	A(int i = 0) :m_i(i) {}
	friend void B::Sub(A& a);//
	friend void B::Print(A& a);
private:
	int m_i;
};
void  B::Sub(A& a)
{
	cout << a.m_i - m_j << endl;
}
void B::Print(A& a)
{
	cout << a.m_i << endl;
}

void main()
{
	A a(40);
	B b(20);
	b.Sub(a);
}

3、类友元

一个类A作为另外一个类B的友元类,则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);
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 <<"print"<< b.m_b << endl;
}
void A::test(B& b)
{
	cout << "test"<<b.m_b << endl;
}
void A::show(B& b)
{
	cout << "show"<<b.m_b << endl;
}
void main()
{
	B b(30);
	A a(40);
	a.print(b);
	a.show(b);
	a.test(b);
}

总结:

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

2、友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果都一样。

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

二、友元特点:

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);
	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;//友元是单向的,需在A中再次声明friend B
}
void A::print(B& b)
{
	cout <<"print"<< b.m_b << endl;
}
void A::test(B& b)
{
	cout << "test"<<b.m_b << endl;
}
void A::show(B& b)
{
	cout << "show"<<b.m_b << endl;
}
void main()
{
	B b(30);
	A a(40);
	a.print(b);
	a.show(b);
	a.test(b);
    b.Print(a);
}

2、友元是不能传递的:A是B的友元,B是C的友元,但A不是C的友元

 BB是AA的朋友,CC是BB的朋友,如果CC没有作为AA的友元类,则CC和AA没有关系——友元不能传递

class BB;
class CC;
class AA
{
public:
	AA(int a=0):m_a(a){}
	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 print(BB& b);
	void test(AA& a);
};
void BB::Show(AA& a)
{
	cout << a.m_a << endl;
}
void CC::print(BB& b)
{
	cout << b.m_b << endl;
}
void CC::test(AA& a)
{
	cout << a.m_a << endl;//error CC不是AA的朋友(友元不能传递)
}
void main()
{
}

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

三、友元函数在运算符重载中的应用

1、不同类型对象,但数据成员个数与类型一致,重载+

class B;
class A
{
public:
	A(int i=0):m_i(i){}
	int operator+(B& b);
private:
	int m_i;
};
class B
{
public:
	B(int j=0):m_j(j){}
	friend int A::operator+(B& b);
private:
	int m_j;
};
int A::operator+(B& b)
{
	return m_i + b.m_j;
}
void main()
{
	A a(10);
	B b(20);
	cout << a + b << endl;//a.+(b)  +(a,b)
}

2、 重载成员函数调用可以省略一个参数

重载友元函数不能省略

class A
{
public:
	A(int i=0):m_i(i){}
	void print()
	{
		cout << m_i << endl;
	}
	A operator+(A& b)//this
	{
		return m_i + b.m_i;
	}
	friend A operator-(A& a, A& b);
	A operator++(int)//a++值返回
	{
		int t = m_i;
		m_i = m_i + 1;
		return t;
	}
	friend A& operator++(A& a);
private:
	int m_i;
};
A operator-(A& a, A& b)
{
	return a.m_i - b.m_i;
}
A& operator++(A& a)
{
	++a.m_i;
	return a;
}
void main()
{
	A a(5);
	A b(10);
	(a + b).print();
	(a - b).print();
	(a++).print();
	(++b).print();
}

3、重载输出运算符(输出对象(即输出对象中的数据成员))

cout——ostream类的对象

cin——istream类的对象

cout<<a;

一般情况下运算符可以解析成下面两种形式:

1、cout.<<(a)  ostream类中重载了<<,程序员不能修改

2、<<(cout,a)  可以在程序员自己定义的类中将<<重载成友元

cout<<a<<b;

cout<<a这个表达式作为了上面的表达式<<左边,返回值为引用 (cout<<a)<<b

(cout<<a)<<b 表达式执行完后,还能继续用<<,说明返回值为ostream类型

friend ostream& operator<<(ostream &out,A &a)

class A
{
public:
	A(int i=0):m_i(i){}
    friend ostream& operator<<(ostream& out, A& a);
private:
	int m_i;
};
//cout<<a<<b  <<(cout,a)
ostream& operator<<(ostream& out, A& a)
{
	out << a.m_i;
	return out;
}
void main()
{
    A a(5);
    cout << a;//cout<<(a)   <<(cout,a)
}

练习: 

输出值为:0,8,5文章来源地址https://www.toymoban.com/news/detail-457317.html

class Magic
{
	double x;
public:
	Magic(double d=0.00):x(fabs(d)){}
	Magic operator+(Magic c)
	{
		return Magic(sqrt(x * x + c.x));
	}
	friend ostream& operator<<(ostream& os, Magic c);
	
};
ostream& operator<<(ostream& os, Magic c)
{
	return os << c.x;
}
void main()
{
	Magic ma;
	cout << ma << "," << Magic(-8) << "," << ma + Magic(-3) + Magic(-4);
}

到了这里,关于C++友元函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 波奇学C++:友元函数,友元类,内部类,匿名对象,优化构造

    这个代码会报错,原因是_a是a._a的私有成员,fun()是类外函数不能访问。 加上友元就可以突破限制 关于友元的知识 友元函数是一种声明,表明这个函数可以访问私有变量。 友元函数本质上不属于类函数,所以这个声明是不受访问限定符限制的,可以定义在public或者private中。

    2024年02月05日
    浏览(27)
  • C++之类的友元函数

    类的友元函数是指在类中声明为友元的函数。友元函数可以访问类的所有成员(包括私有成员),但它本身并不是类的成员函数,因此不需要通过类的对象来调用。友元函数主要用于在类的内部实现对其他类成员的访问和操作。 举例说明: 这个友元函数的参数是一个类A的对象引

    2024年01月22日
    浏览(26)
  • C++——详解类模板与友元函数

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 模板类的友元函数有三类: 1)非模板友元函数:友元函数不是模板函数,而是利用模板类参数生成的函数。 2)约束模板友元函数:模板类实例化时,每个实例化的类对应一个友元函数。 3)非约束

    2024年02月11日
    浏览(27)
  • python如何调用另外一个py文件中的函数

    在Python中,可以通过导入模块的方式调用另外一个.py文件中的函数。具体步骤如下: 创建一个.py文件,其中包含需要调用的函数,例如: 在调用该函数的代码文件中,使用 import 导入这个.py文件(注意,要确保两个文件处于同一目录下),例如: 在这个例子中,首先

    2024年02月11日
    浏览(513)
  • C++类和对象终章——友元函数 | 友元类 | 内部类 | 匿名对象 | 关于拷贝对象时一些编译器优化

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 、 Linu

    2023年04月15日
    浏览(30)
  • 运维Shell脚本小试牛刀(七):在函数文脚本件中调用另外一个脚本文件中函数|函数递归调用|函数后台执行

    运维Shell脚本小试牛刀(一) 运维Shell脚本小试牛刀(二) 运维Shell脚本小试牛刀(三)::$(cd $(dirname $0); pwd)命令详解 运维Shell脚本小试牛刀(四): 多层嵌套if...elif...elif....else fi_蜗牛杨哥的博客-CSDN博客 Cenos7安装小火车程序动画 运维Shell脚本小试牛刀(五):until循环 运维Shell脚本小试牛刀

    2024年02月09日
    浏览(42)
  • 【C++】类和对象(下篇)--->再识构造函数,static成员,友元,内部类,匿名对象

    目录 一、构造函数  1、构造函数体赋值  2、初始化列表  3、explicit 二、Static 成员  1、概念  2、特性 三、友元  1、友元函数  2、友元类 四、内部类  1、概念  2、特性 五、匿名对象 六、拷贝对象时的一些编译器优化 在创建对象时,编译器通过调用构造函数,给对

    2024年02月13日
    浏览(30)
  • c++类开发的第三篇(讲明白友元函数和this指针)

    c++实现了 封装 , 数据 和 处理数据的操作(函数) 是分开存储的。 c++中的 非静态数据成员 直接内含在类对象中,就像c语言的struct一样。 成员函数并不会出现在对象中,而是作为类的一部分存储在代码段中,需要通过对象或对象指针进行调用。成员函数可以访问类的所有成员

    2024年02月21日
    浏览(35)
  • c++中static静态成员变量和静态成员函数、explcit和隐式类型转换、友元函数()详解

    声明为 static 的类成员 称为 类的静态成员 ,用 static 修饰的 成员变量 ,称之为 静态成员变量 ;用 static 修饰 的 成员函数 ,称之为 静态成员函数 。 静态成员变量一定要在类外进行初始化   静态成员 为 所有类对象所共享 ,不属于某个具体的对象,存放在静态区   静态成

    2024年02月04日
    浏览(38)
  • [C++]类和对象,explicit,static,友元,构造函数——喵喵要吃C嘎嘎4

    希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,大大会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要! 佬佬催更,那就更吧!嗯~ o(* ̄▽ ̄*)o! 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个

    2024年03月15日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包