精华内容
下载资源
问答
  • 现在先说说赋值运算符“=”的重载C++规定赋值运算符“=”只能重载为类的非静态成员函数,而不可以重载为类的友元函数。不能重载为类的静态成员应该比较容易理解,因为静态成员函数是属于整个类的,不是属于某个对象...
  • C++——友元函数&内联函数

    千次阅读 多人点赞 2018-12-07 23:55:15
    友元函数 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。 友元可以是一个函数,该函数被...

    友元函数

    类的友元函数是定义在类外部但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数

    友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

    如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:

    class Box
    {
       double width;
    public:
       double length;
       friend void printWidth( Box box );
       void setWidth( double wid );
    };
    #include <iostream>
     
    using namespace std;
     
    class Box
    {
       double width;
    public:
       friend void printWidth( Box box );
       void setWidth( double wid );
    };
    
    // 成员函数定义
    void Box::setWidth( double wid )
    {
        width = wid;
    }
    
    // printWidth() 不是任何类的成员函数
    void printWidth( Box box )
    {
       /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
       cout << "Width of box : " << box.width <<endl;
    }
     
    // 程序的主函数
    int main( )
    {
       Box box;
     
       // 使用成员函数设置宽度
       box.setWidth(10.0);
       
       // 使用友元函数输出宽度
       printWidth( box );
     
       return 0;
    }
    /*输出结果是
    Width of box : 10
    */

    内联函数

    内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。

    对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。

    如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。

    在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。

     

    #include <iostream>
     
    using namespace std;
    
    inline int Max(int x, int y)
    {
       return (x > y)? x : y;
    }
    
    // 程序的主函数
    int main( )
    {
    
       cout << "Max (20,10): " << Max(20,10) << endl;
       cout << "Max (0,200): " << Max(0,200) << endl;
       cout << "Max (100,1010): " << Max(100,1010) << endl;
       return 0;
    }

    以下内容转载自:https://blog.csdn.net/u011327981/article/details/50601800/

    1.  内联函数

    在C++中我们通常定义以下函数来求两个整数的最大值:

    复制代码 代码如下:


    int max(int a, int b)
    {
     return a > b ? a : b;
    }

    为这么一个小的操作定义一个函数的好处有:

    ① 阅读和理解函数 max 的调用,要比读一条等价的条件表达式并解释它的含义要容易得多

    ② 如果需要做任何修改,修改函数要比找出并修改每一处等价表达式容易得多

    ③ 使用函数可以确保统一的行为,每个测试都保证以相同的方式实现

    ④ 函数可以重用,不必为其他应用程序重写代码

    虽然有这么多好处,但是写成函数有一个潜在的缺点:调用函数比求解等价表达式要慢得多。在大多数的机器上,调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行

    C++中支持内联函数,其目的是为了提高函数的执行效率,用关键字 inline 放在函数定义(注意是定义而非声明,下文继续讲到)的前面即可将函数指定为内联函数,内联函数通常就是将它在程序中的每个调用点上“内联地”展开,假设我们将 max 定义为内联函数:

    复制代码 代码如下:


    inline int max(int a, int b)
    {
     return a > b ? a : b;
    }

    则调用: cout<<max(a, b)<<endl;


    在编译时展开为: cout<<(a > b ? a : b)<<endl;

    从而消除了把 max写成函数的额外执行开销

    2.  内联函数和宏

    无论是《Effective C++》中的 “Prefer consts,enums,and inlines to #defines” 条款,还是《高质量程序设计指南——C++/C语言》中的“用函数内联取代宏”,宏在C++中基本是被废了,在书《高质量程序设计指南——C++/C语言》中这样解释到:

    3.  将内联函数放入头文件

    关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。

    如下风格的函数 Foo 不能成为内联函数:

    复制代码 代码如下:


    inline void Foo(int x, int y);   // inline 仅与函数声明放在一起   
    void Foo(int x, int y)
    {
     ...

    而如下风格的函数 Foo 则成为内联函数:

    复制代码 代码如下:


    void Foo(int x, int y);   
    inline void Foo(int x, int y)   // inline 与函数定义体放在一起
    {
     ...

    所以说,C++ inline函数是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了 inline 关键字,但我认为 inline 不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。

    定义在类声明之中的成员函数将自动地成为内联函数,例如:

    复制代码 代码如下:


    class A
    {  
    public:
     void Foo(int x, int y) { ... }   // 自动地成为内联函数  

    但是编译器是否将它真正内联则要看 Foo函数如何定义

    内联函数应该在头文件中定义,这一点不同于其他函数。编译器在调用点内联展开函数的代码时,必须能够找到 inline 函数的定义才能将调用函数替换为函数代码,而对于在头文件中仅有函数声明是不够的。

    当然内联函数定义也可以放在源文件中,但此时只有定义的那个源文件可以用它,而且必须为每个源文件拷贝一份定义(即每个源文件里的定义必须是完全相同的),当然即使是放在头文件中,也是对每个定义做一份拷贝,只不过是编译器替你完成这种拷贝罢了。但相比于放在源文件中,放在头文件中既能够确保调用函数是定义是相同的,又能够保证在调用点能够找到函数定义从而完成内联(替换)。

    但是你会很奇怪,重复定义那么多次,不会产生链接错误?

    我们来看一个例子:

    A.h :

    复制代码 代码如下:


    class A
    {
    public:
     A(int a, int b) : a(a),b(b){}
     int max();

    private:
     int a;
     int b;
    };

    A.cpp : 

    复制代码 代码如下:


    #include "A.h"

    inline int A::max()
    {
     return a > b ? a : b;
    }

    Main.cpp : 

    复制代码 代码如下:


    #include <iostream>
    #include "A.h"
    using namespace std;

    inline int A::max()
    {
     return a > b ? a : b;
    }

    int main()
    {
     A a(3, 5);
     cout<<a.max()<<endl;
     return 0;
    }

    一切正常编译,输出结果:5

     


    倘若你在Main.cpp中没有定义max内联函数,那么会出现链接错误:

    error LNK2001: unresolved external symbol "public: int __thiscall A::max(void)" (?max@A@@QAEHXZ)main.obj
    找不到函数的定义,所以内联函数可以在程序中定义不止一次,只要 inline 函数的定义在某个源文件中只出现一次,而且在所有源文件中,其定义必须是完全相同的就可以。

    在头文件中加入或修改 inline 函数时,使用了该头文件的所有源文件都必须重新编译。

    4.  慎用内联

    内联虽有它的好处,但是也要慎用,以下摘自《高质量程序设计指南——C++/C语言》:

    而在Google C++编码规范中则规定得更加明确和详细:

    内联函数:

    Tip: 只有当函数只有 10 行甚至更少时才将其定义为内联函数.

    定义: 当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.
    优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.
    缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。
    结论: 一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!
    另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).
    有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要; 比如虚函数和递归函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数.(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数). 虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.

    -inl.h文件:


    Tip: 复杂的内联函数的定义, 应放在后缀名为 -inl.h 的头文件中.


    内联函数的定义必须放在头文件中, 编译器才能在调用点内联展开定义. 然而, 实现代码理论上应该放在 .cc 文件中, 我们不希望 .h 文件中有太多实现代码, 除非在可读性和性能上有明显优势.

    如果内联函数的定义比较短小, 逻辑比较简单, 实现代码放在 .h 文件里没有任何问题. 比如, 存取函数的实现理所当然都应该放在类定义内. 出于编写者和调用者的方便, 较复杂的内联函数也可以放到 .h 文件中, 如果你觉得这样会使头文件显得笨重, 也可以把它萃取到单独的 -inl.h 中. 这样把实现和类定义分离开来, 当需要时包含对应的 -inl.h 即可。

     

    部分资料来源于菜鸟教程

    展开全文
  • 今天小编就为大家分享一篇关于在C++中关于友元函数的进一步理解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 一般情况下,使用一个函数需要先声明,或者定义在前,但是声明一个全局函数为友元函数的时候,可以理解为只是声明,而非调用,因此不用先在类的前面声明该全局函数。另外,如果要在类的前面声明该友元函数,需要用到...

    友元声明

    前面加上关键字friend,该声明可以放在任何一个地方,一般放在类的定义中。当声明了友元函数或者友元类之后,该函数或者类可以访问类的所有成员,包括private成员,当然访问过程需要通过类的对象进行。例如声明一个友元函数/类,有三种情况:
    ①友元是普通的全局函数
    一般情况下,使用一个函数需要先声明,或者定义在前,但是声明一个全局函数为友元函数的时候,可以理解为只是声明,而非调用,因此不用先在类的前面声明该全局函数。另外,如果要在类的前面声明该友元函数,需要用到类,因此还得在该声明的前面声明类的定义,比较麻烦。故总结顺序如下:类的定义,类中友元函数声明,类后友元函数实现。 这样的顺序应该万无一失了。

    #include<iostream>
    using namespace std;
    
    class student{
    	friend func(student *stu);//声明全局函数func为友元函数,不用在类前面声明,定义在后面。
    	private:
    		int age;
    //		void set_age(int t_age):age(t_age){};//不能使用初始化列表
    		void set_age(int t_age)
    		{
    			age = t_age;
    		 } 
    	public:
    		student(int t_age):age(t_age){};
    		void show_age(){cout<<"age = "<<age<<endl;};
    }; 
    void func(student *stu){
    	stu->set_age(-1); //可以通过对象访问private成员 
    	stu->show_age(); //当然也可以访问public成员
    }
    int main()
    {
    	student* stu = new student(10);
    	func(stu); //结果为: age = -1;
    	//查看age是否被修改
    	stu->show_age(); //结果为-1
    	//注意不能直接输出cout<<stu->age<<endl;
    	return 0;
    }
    

    这里刚开始的时候出了一个问题,set_age函数我使用了初始化列表,然后报错,搜查之后发现错误原因在于初始化列表的使用,注意:只有构造函数初始化的时候能使用初始化列表
    这里又发现了一个新的问题,在经过func函数之后,我想查看stu中的private成员age是否发生了变化,于是我试图通过直接输出age:

    cout << stu->age << endl;
    

    但是发现不可以,难道对象自己不能直接访问自己的私有数据成员么?
    查阅资料之后发现解释如下,private,public是针对类外的对象,类外的其他类对象的,这里stu定义在类外,因此不能访问私有数据成员。但是有一个例外,那就是友元函数,友元函数可以直接访问。而定义在类内的成员函数可以直接访问。总结一句话就是:在类内定义,可以访问,在类外定义,不能访问,友元函数可以访问
    ②友元是一个类
    同友元是一个函数一样,友元类可以先不定义,在当前类中声明友元类不会报错。所以顺序应该为:当前类的定义,类中声明友元类,友元类定义
    当然,如果先定义友元类,那么在友元类之前需要声明当前类。

    #include<iostream>
    using namespace std;
    
    class student {
    	friend class teacher; //声明一个友元类
    	//该友元类teacher还没有声明/定义,不会报错。
    private:
    	int age;
    	void set_age(int t_age);
    public:
    	student(int t_age) :age(t_age) {};
    	void show_age();
    };
    //友元类的实现
    class teacher {
    public:
    	teacher() {};
    	void func(student *stu); //如果把友元类定义在前,那么需要先声明student类,否则报错
    };
    void teacher::func(student* stu)
    {
    	stu->set_age(-1);
    	stu->show_age();
    }
    void student::set_age(int t_age)
    {
    	age = t_age;
    }
    void student::show_age()
    {
    	cout<<"age = "<<age<<endl;
    }
    int main()
    {
    	teacher* tea = new teacher();
    	student* stu = new student(10);
    	tea->func(stu); //age = -1
    	return 0;
    }
    

    ③友元是类中的一个成员函数
    这里需要注意的是:被声明为友元函数的成员函数必须定义在该类的前面,也就是这个成员函数所属的类在该类的前面定义,里面的成员函数可以只是先声明。也就是友元函数的类定义要在前面定义。但是问题来了,友元函数中的参数类型是当前类,所以得提前声明当前类。因此顺序为:当前类声明,友元类定义,当前类定义,两个类各种函数的具体实现。

    #include<iostream>
    using namespace std;
    class student; //必须提前声明,因为友元类中的函数要用到
    //友元函数所属类的定义必须在前,具体函数实现可以最后考虑
    class teacher {
    public:
    	teacher() {};
    	void func(student* stu); //友元函数
    };
    
    class student {
    	friend void teacher::func(student *stu); //声明一个类中的成员函数为友元函数
    private:
    	int age;
    	void set_age(int t_age);
    public:
    	student(int t_age) :age(t_age) {};
    	void show_age();
    };
    //两个类中的成员函数实现
    void teacher::func(student* stu)
    {
    	stu->set_age(-1);
    	stu->show_age();
    }
    void student::set_age(int t_age)
    {
    	age = t_age;
    }
    void student::show_age()
    {
    	cout<<"age = "<<age<<endl;
    }
    int main()
    {
    	student* stu = new student(10);
    	teacher* tea = new teacher();
    	tea->func(stu); //teacher类中的成员函数func被student类声明为友元函数,该函数可以访问student类所定义的对象的private成员
    
    	return 0;
    }
    
    

    最后需要注意两点:
    派生类中的友元函数对其基类不起作用,不能访问基类的private成员
    只有当某个类中的成员函数的定义都完整给出之后才能定义该类的对象。可以理解为,定义还没完成,无法确定存储空间大小,也就无法生成一个对象。

    展开全文
  • 友元可以是一个普通函数,成员函数或者另外一个类。】 友元是非对称的,非传递的。除非特别声明。 在一个类A中,如果将关键字friend冠于一个函数原型或类名之前,则该函数或类成为类A的友元。 例: class A { ...

    一个对象的私有数据,只能通过成员函数访问。
    但是C++提供了一种辅助手段——定义类的友元。【友元可以访问类的所有成员。友元可以是一个普通函数,成员函数或者另外一个类。】
    友元是非对称的,非传递的。除非特别声明。
    在一个类A中,如果将关键字friend冠于一个函数原型或类名之前,则该函数或类成为类A的友元。
    例:

    class A
    {
    private:
    int i;
    void MemberFun(int);
    friend void FriendFun(A*,int)
    }

      void FriendFun(A*ptr,int x)            //友元函数通过**参数**访问类的私有数据成员
      { ptr->i=x;};
      void A::MemberFun(int x)             //成员函数通过**this**指针访问类的私有数据成员
      { i=x;};
    

    友元函数必须在参数表中显示地指明要访问的对象(就像朋友要用你的东西时要标注你的名字)
    例:
    A Aobj;
    FriendFun(&Aobj,5); //指明对象Aobj【通过对象访问私有数据成员。】
    Aobj.MemberFun(5); //通过对象调用类的成员函数。

    展开全文
  • 借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。friend 的意思是朋友,或者说是好友,与好友的关系显然要比一般人亲密一些。我们会对好朋友敞开心扉,倾诉自己的...

    在C++中,一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员。现在,我们来介绍一种例外情况——友元(friend)。借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。

    friend 的意思是朋友,或者说是好友,与好友的关系显然要比一般人亲密一些。我们会对好朋友敞开心扉,倾诉自己的秘密,而对一般人会谨言慎行,潜意识里就自我保护。在 C++ 中,这种友好关系可以用 friend 关键字指明,中文多译为“友元”,借助友元可以访问与其有好友关系的类中的私有成员。如果你对“友元”这个名词不习惯,可以按原文 friend 理解为朋友。

    友元函数

    在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。友元函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数。

    友元函数可以访问当前类中的所有成员,包括 public、protected、private 属性的。

    1) 将非成员函数声明为友元函数。

    请大家直接看下面的例子:

    #include <iostream>
    using namespace std;
    
    class Student{
    public:
        Student(char *name, int age, float score);
    public:
        friend void show(Student *pstu);  //将show()声明为友元函数
    private:
        char *m_name;
        int m_age;
        float m_score;
    };
    
    Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
    
    //非成员函数
    void show(Student *pstu){
        cout<<pstu->m_name<<"的年龄是 "<<pstu->m_age<<",成绩是 "<<pstu->m_score<<endl;
    }
    
    int main(){
        Student stu("小明", 15, 90.6);
        show(&stu);  //调用友元函数
        Student *pstu = new Student("李磊", 16, 80.5);
        show(pstu);  //调用友元函数
    
        return 0;
    }
    
    //运行结果:
    //小明的年龄是 15,成绩是 90.6
    //李磊的年龄是 16,成绩是 80.5

    show() 是一个全局范围内的非成员函数,它不属于任何类,它的作用是输出学生的信息。m_name、m_age、m_score 是 Student 类的 private 成员,原则上不能通过对象访问,但在 show() 函数中又必须使用这些 private 成员,所以将 show() 声明为 Student 类的友元函数。


    注意,友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。下面的写法是错误的:

    void show()
    {
        cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
    }
    
    
    
    
    
    成员函数在调用时会隐式地增加 this 指针,指向调用它的对象,从而使用该对象的成员;而 show() 是非成员函数,没有 this 指针,编译器不知道使用哪个对象的成员,要想明确这一点,就必须通过参数传递对象(可以直接传递对象,也可以传递对象指针或对象引用),并在访问成员时指明对象。
    

    2) 将其他类的成员函数声明为友元函数

    friend 函数不仅可以是全局函数(非成员函数),还可以是另外一个类的成员函数。请看下面的例子:

    #include <iostream>
    using namespace std;
    
    class Address;  //提前声明Address类
    
    //声明Student类
    class Student{
    public:
        Student(char *name, int age, float score);
    public:
        void show(Address *addr);
    private:
        char *m_name;
        int m_age;
        float m_score;
    };
    
    //声明Address类
    class Address{
    private:
        char *m_province;  //省份
        char *m_city;  //城市
        char *m_district;  //区(市区)
    public:
        Address(char *province, char *city, char *district);
        //将Student类中的成员函数show()声明为友元函数
        friend void Student::show(Address *addr);
    };
    
    //实现Student类
    Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
    void Student::show(Address *addr){
        cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
        cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"区"<<endl;
    }
    
    //实现Address类
    Address::Address(char *province, char *city, char *district){
        m_province = province;
        m_city = city;
        m_district = district;
    }
    
    int main(){
        Student stu("小明", 16, 95.5f);
        Address addr("陕西", "西安", "雁塔");
        stu.show(&addr);
       
        Student *pstu = new Student("李磊", 16, 80.5);
        Address *paddr = new Address("河北", "衡水", "桃城");
        pstu -> show(paddr);
    
        return 0;
    }
    
    //运行结果:
    //小明的年龄是 16,成绩是 95.5
    //家庭住址:陕西省西安市雁塔区
    //李磊的年龄是 16,成绩是 80.5
    //家庭住址:河北省衡水市桃城区


    本例定义了两个类 Student 和 Address,程序第 27 行将 Student 类的成员函数 show() 声明为 Address 类的友元函数,由此,show() 就可以访问 Address 类的 private 成员变量了。

    几点注意:
    ① 程序第 对Address 类进行了提前声明,是因为在 Address 类定义之前、在 Student 类中使用到了它,如果不提前声明,编译器会报错,提示'Address' has not been declared类的提前声明和函数的提前声明是一个道理。

    ② 程序将 Student 类的声明和实现分开了,而将 Address 类的声明放在了中间,这是因为编译器从上到下编译代码,show() 函数体中用到了 Address 的成员 province、city、district,如果提前不知道 Address 的具体声明内容,就不能确定 Address 是否拥有该成员(类的声明中指明了类有哪些成员)。

    ③ 一个函数可以被多个类声明为友元函数,这样就可以访问多个类中的 private 成员。

     

    友元类

    不仅可以将一个函数声明为一个类的“朋友”,还可以将整个类声明为另一个类的“朋友”,这就是友元类。友元类中的所有成员函数都是另外一个类的友元函数。

    例如将类 B 声明为类 A 的友元类,那么类 B 中的所有成员函数都是类 A 的友元函数,可以访问类 A 的所有成员,包括 public、protected、private 属性的。

    更改上例的代码,将 Student 类声明为 Address 类的友元类:

    #include <iostream>
    using namespace std;
    
    class Address;  //提前声明Address类
    
    //声明Student类
    class Student{
    public:
        Student(char *name, int age, float score);
    public:
        void show(Address *addr);
    private:
        char *m_name;
        int m_age;
        float m_score;
    };
    
    //声明Address类
    class Address{
    public:
        Address(char *province, char *city, char *district);
    public:
        //将Student类声明为Address类的友元类
        friend class Student;
    private:
        char *m_province;  //省份
        char *m_city;  //城市
        char *m_district;  //区(市区)
    };
    
    //实现Student类
    Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
    void Student::show(Address *addr){
        cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
        cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"区"<<endl;
    }
    
    //实现Address类
    Address::Address(char *province, char *city, char *district){
        m_province = province;
        m_city = city;
        m_district = district;
    }
    
    int main(){
        Student stu("小明", 16, 95.5f);
        Address addr("陕西", "西安", "雁塔");
        stu.show(&addr);
       
        Student *pstu = new Student("李磊", 16, 80.5);
        Address *paddr = new Address("河北", "衡水", "桃城");
        pstu -> show(paddr);
    
        return 0;
    }

    将 Student 类声明为 Address 类的友元类,声明语句为:

    friend class Student;

    有的编译器也可以不写 class 关键字,不过为了增强兼容性还是建议写上。

    关于友元,有两点需要说明:

    • 友元的关系是单向的而不是双向的。如果声明了类 B 是类 A 的友元类,不等于类 A 是类 B 的友元类,类 A 中的成员函数不能访问类 B 中的 private 成员。
    • 友元的关系不能传递。如果类 B 是类 A 的友元类,类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。

    除非有必要,一般不建议把整个类声明为友元类,而只将某些成员函数声明为友元函数,这样更安全一些。

    展开全文
  • 友元函数

    2019-04-27 22:56:39
       友元函数是C++中,成员函数或者类外函数访问类里的私有数据成员用的比较方便的函数,友元函数的关键字是friend,我们暂时把它理解成“友好关系”的意思。    我们用两个类来比喻这种关系吧。 二.友元函数...
  • 对于单目运算符,也可以重载为类的友元函数,该友元函数有一个参数,前置自增和自减运算符重载为类的友元函数时, 该函数有一个参数,即该类的对象; 后置自增和自减运算符重载为类的友元函数时,有两个参数,第一...
  • 搬运自:... ... 友元包括友元函数、友元类 友元函数: 个人理解为在类中声明的可以外部访问类的内部成员变量的一个函数,这个函数并不是类的成员函数,只是在类中声明,而定义在类外。换...
  • 什么场景下会用到友元函数

    千次阅读 2017-10-11 07:56:42
    什么场景下会用到友元函数友元函数的作用是什么,友元函数和普通成员函数又有怎样的区别?这都是C++当中的一些基本概念,掌握好了无论是维护项目还是做项目开发都大有裨益。本文主要浅谈一下C++中的友元函数,如有...
  • 关于C++中的friend友元函数的总结

    万次阅读 多人点赞 2018-12-07 10:05:18
    1.友元函数的简单介绍 1.1为什么要使用友元函数 在实现类之间数据共享时,减少系统开销,提高效率。如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数。 具体来说:...
  • 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。 友元可以是一个函数,该函数被称为友元函数...
  • 友元函数的使用方式

    2021-04-07 19:58:15
    一、介绍 个人认为该函数的作用及时能够是: 非成员函数可以使用 私有的 成员变量 用途: 便于写 sort函数 和 优先...借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成
  • 参考链接 [url]http://blog.csdn.net/insistgogo/article/details/6608672[/url] [url]... [b]1、为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率[/b] 具体来...
  • 以前总是对friend感到迷茫,其实很简单,自己总结了一下,欢迎交流
  • 版权声明:本文为博主原创文章,未经博主允许不得转载。... ... 在学习c++这一块,关于友元函数和友元类,感觉还是不好理解,但是井下心来,理解,需要把我一下几...
  • 全局函数、类成员函数 作为友元函数 #include "stdafx.h" #include using namespace std; #if 0 同类对象间无私处 异类对象间有友员 //函数(可以是全局函数,也可是类成员函数)可以作友元,称为友元函数 //友元...
  • 对c++友元函数和友元类的理解

    千次阅读 2016-06-26 20:44:00
    1,友元函数的定义和作用 我们已知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为...
  • 友元函数和友元类

    2018-08-24 16:34:53
    https://www.cnblogs.com/staring-hxs/p/3432161.html
  • 友元函数(friend function) 1. 什么是友元函数?  一个类的私有数据成员通常只能由类的函数成员来访问,而友元... 2.2 用友元函数可以访问两个或多个类的私有数据,较其它方法使人们更容易理解程序的逻辑关系 3....
  • 一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 ...友元可以访问与其有好友关系的类中的私有成员,友元包括友元函数和友元类。如果您对友元这个名词不习惯,可以按原文 friend 理解
  • 用成员函数和友元函数重载运算符

    千次阅读 2019-05-20 10:25:04
    友元函数和成员函数选择 1.当无法修改左操作数的类时,使用全局函数进行重载 2.=、[]、()和->操作符只能通过成员函数进行重载 用友元函数重载<<、>>操作符 ostream& operator<<...
  • 静态函数毫无疑问具有类作用域,而友元函数本身可能是全局函数、也可能是其他类的成员函数,所以我猜测是不是可以理解为静态函数是友元函数的一种特例。 接下来,我想验证友元函数是否也可以具有类作用域,所以我...
  • 友元函数3. 友元类4. 友元成员函数 1. 前言 友元,一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。贴一下百度百科的解释百度百科-友元...
  • c++友元函数简单理解

    2020-05-23 15:23:05
    友元函数的使用 因为友元函数没有this指针,则参数要有三种情况: 要访问非static成员时,需要对象做参数; 要访问static成员或全局变量时,则不需要对象做参数; 如果做参数的对象是全局对象,则不需要对象做...
  • c++类模板和友元函数的特殊情况 我会将类模板的成员函数和友元函数做对比 一 、普通类模板 创建一个Demo类模板: 这是一个普通类模板,里面的T是虚拟的类型参数。在每一个类模板的成员函数实现之前要加模板声明,成员...
  • 彻底搞懂static成员和友元函数、类(lesson 4) static成员 运算符重载的左右操作数 友元 总结 1)static成员 在C语言里static可以修饰变量和函数: 函数: 改变函数的链接属性,表明该函数只能在当前文件中使用 ...
  • 重载运算符与友元函数

    千次阅读 2017-08-30 21:26:51
    本次博客 主要学习运算符重载和友元函数。其中 运算符重载能够将平时用于内置类型的变量的操作符(如+,-,*,/等)用于类对象; 友元这种C++机制使得非成员函数可以访问私有数据。
  • 友元函数(friend function) 1. 什么是友元函数?  一个类的私有数据成员通常只能由类的函数成员来访问,而友元函数可以... 2.2 用友元函数可以访问两个或多个类的私有数据,较其它方法使人们更容易理解程序的逻辑

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,010
精华内容 4,404
关键字:

友元函数的理解