精华内容
下载资源
问答
  • 1.友元函数调用类成员变量要先定义类对象,然后通过对象调用,并且可以访问任何成员,成员函数就不需要定义类对象,可以直接使用数据成员, 2.友元函数成员函数的定义方式不同,友元函数有个friend修饰 3.定义...

    1.友元函数调用类成员变量要先定义类对象,然后通过对象调用,并且可以访问任何成员,成员函数就不需要定义类对象,可以直接使用数据成员,

    2.友元函数和成员函数的定义方式不同,友元函数有个friend修饰

    3.定义友元函数,不需要加类名

    4.调用友元函数不需要通过,类对象

     

     

    展开全文
  • 友元函数既可以是不属于任何类的非成员函数(全局函数),也可以是另一个类的成员函数(友元化时函数名前要加上所属的类),本文主要讨论一个类的成员函数如何成为另一个类的友元函数 具体实现 # include <...

    C++:成员友元函数(成员函数友元化)

    友元函数

    友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。

    友元函数既可以是不属于任何类的非成员函数(全局函数),也可以是另一个类的成员函数(友元化时函数名前要加上所属的类),本文主要讨论一个类的成员函数如何成为另一个类的友元函数

    具体实现

    # include <iostream>
    # include <string>
    using namespace std;
    
    class Student;//对Student类的提前引用声明
    class Teacher 
    {
    private:
    	int num;
    	string name;
    	string sex;
    public:
    	Teacher(int n, string na, string s) { num = n; name = na; sex = s; }
    	//如果之前没有对对Student类做提前引用声明,底下就会报错无法识别Student类
    	void transform(Student& b);
    	Teacher(){};
    	void  display()
    	{
    		cout << "TEACHER:" << endl;
    		cout << num << endl;
    		cout << name << endl;
    		cout << sex << endl;
    	}
    };
    
    class Student
    {
    public:
    	Student(int n, string na, string s):num(n), name(na), sex(s) {};
    	void display()
    	{
    		cout << "student:" << endl;
    		cout << num << endl;
    		cout << name << endl;
    		cout << sex << endl;
    	}
    	friend void Teacher::transform(Student& b);
    private:
    	int num;
    	string name;
    	string sex;
    };
    //transform函数的具体定义一定要写在Student类完整定义之后,否则函数中对类中成员的使用会报错
    void Teacher::transform(Student& b)
    {   
    		num=b.num;
    		name=b.name;
    		sex=b.sex;
    }
    
    int main()
    {
    	Student t(12, "玛奇玛", "女");
    	t.display();
    	Teacher s;
        s.transform(t);
    	cout<<"转换后:"<<endl;
    	s.display();
    	return 0;
    }
    

    运行结果:
    运行结果

    说明

    提前引用声明注意事项

    我们知道C++的类应当是先定义,然后使用。但在处理相对复杂的问题、考虑类的组合时,很可能遇到俩个类相互引用的情况,这种情况称为循环依赖。(列如头文件互引)

    这里类Teacher的公有成员函数transform的形参是类Student的对象,同时类Student的友元函数也属于Teacher类。由于在使用一个类之前,必须首先定义该类,因此无论将哪一个类的定义放在前面,都会引起编译错误。结局这个问题的方法,就是使用前向引用声明。前向引用声明,是在引用未定义的类之前,将该类的名字告诉编译器,编译器知道那是一个类名。这样,当程序中使用这个类名时,编译器就不会认为是错误,而类的完整定义可以在程序的其他地方。在上述程序加上下面的前向引用声明,问题就解决了。

    使用前向引用声明虽然可以解决一些问题,但它并不是万能的。需要注意的是,尽管使用了前向引用声明, 但是在提供一个完整的类定义之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象(及类中的成员),上述案例中就是在Student类完整定义之后再定义Teacher类的成员函数transform,另一个案例如下

    class Fred;    //前向引用声明
    class Barney
    {
        Fred x;    //错误:类Fred的声明尚不完善
    };
    class Fred
    {
        Barney y;
    };
    

    编译出错的原因是对此类Fred的前向引用声明只能说明Fred是一个类名,而不能给出该类的完整定义,因此在类Barney中不能定义或使用类Fred的数据成员。

    应该记住:当你使用前向引用声明时,你只能使用被声明的符号,而不能涉及类的任何细节。

    C++的类可以进行前向声明。但是,仅仅进行前向声明而没有定义的类是不完整的,这样的类, 只能用于定义指针、引用、以及用于函数形参的指针和引用。
    而不能定义对象(因为此时编译器只知道这是个类,还不知道这个类的大小有多大),也不能访问类的对象,任何形式的访问都不允许(因为此时根本不知道有些什么成员)。等到类正式定义以后,就可以以各种方式使用该类了。

    参考:
    https://blog.csdn.net/weixin_30604651/article/details/98868240
    https://blog.csdn.net/weixin_30800807/article/details/95889531

    展开全文
  • 最近开始看《Effective C++》,为了方便以后回顾,特意做了笔记。若本人对书中的知识点理解有误的话,望请指正!!! 假设用一个 class 来表示网页浏览器,这样... //把调用上述的三个函数的操作封装到一个函数内 void

    最近开始看《Effective C++》,为了方便以后回顾,特意做了笔记。若本人对书中的知识点理解有误的话,望请指正!!!

    假设用一个 class 来表示网页浏览器,这样的 class 中有清除缓存、清除历史纪录以及清除 cookies 的函数:

    class WebBrowser{
    public:
        void clearCache();
        void clearHistory();
        void removeCookies();
        //把调用上述的三个函数的操作封装到一个函数内
        void clearEverything(){
            clearCache();
            clearHistory();
            removeCookies();
        }
      	...
    };
    

    许多用户会想把清除缓存、清除历史纪录以及清除cookies的动作封装到一个函数内,所以 WebBrowser 提供了 clearEverything() 函数。当然,这一个函数也可用非成员函数实现:

    void cleanBrowser(WebBrowser& wb){
        wb.clearCache();
        wb.clearHistory();
        wb.removeCookies();
    }
    

    我们有两种选择,哪种更好呢?

    面向对象守则要求数据以及操作数据的函数应该封装在 class 内,那么成员函数是更好的选择?这是错误的,面向对象守则要求数据应该尽可能被封装,然而成员函数 clearEverything()带来的封装性比非成员函数 cleanBrowser() 低。此外,提供非成员函数 WebBrowser 相关机能有较大的包装弹性(packaging flexibility),而这导致较低的编译相依度,增加 WebBrowser 的可延伸性。

    条款22说过,成员变量应该声明为 private ,不然它们就毫无封装性,而能够访问 private 成员变量的函数只有 class 的成员函数和友元函数。如果你要在一个成员函数(它不止可以访问 class 内的 private 数据、也可以调用 private 函数、enum、typedef 等)和一个非成员函数(它无法访问上述任何东西)之间做抉择,且两者提供相同机能,那么选择较大封装性的 非成员函数 是最好的。

    在这一点上有两件事情需要注意:

    • 这个论述只适用于非成员非友元函数。友元函数对 class 内的 private 成员的访问权限和成员函数相同,因此两者对封装的冲击力度也相同。从封装角度看,这里的选择关键并不在成员函数和非成员函数之间,而是在成员函数和非成员非友元函数之间。(封装并非唯一考虑,条款24解释当我们考虑隐式类型转换,应该在成员函数和非成员函数之间抉择)
    • 以上并不是说这个函数就不能在别的类里。例如我们可以写一个工具类(utility class),然后把 cleanBrowser() 作为它的一个静态成员函数,只要这个函数不在 WebBrowser 里就不会影响其 private 成员的封装。

    在C++中,比较自然的做法是让 cleanBrowser() 成为一个非成员函数并且位于 WebBrowser 所在的同一个命名空间内:

    namespace WebBrowserStuff{
        class WebBrowser{...};
        void cleanBrowser(WebBrowser& wb){...}
    }
    

    命名空间和类不同,前者可跨越多个源码文件而后者不能。因为像 cleanBrowser()这样的函数是个“提供便利的函数”,如果它不是成员函数也不是友元,就没有对 WebBrowser 的特殊访问权力。

    一个像WebBrowser 这样的类可能拥有大量的便利函数,某些与书签有关,某些与打印有关,还有些与cookie的管理有关等,通常用户只对某一些感兴趣。就好像一个只对书签相关便利函数感兴趣的用户与一个cookie相关便利函数发生编译相依关系。分离它们的最直接做法就是将它们分别声明于不同的头文件内:

    //webbrowser.h 包含浏览器的核心功能
    namespace WebBrowserStuff{
    class WebBrowser{...};	//浏览器类
        ...	//核心机能
            //非成员函数
    }
    
    //webbrowserbookmarks.h 
    namespace WebBrowserStuff{
        ...	//与书签相关的便利函数
    }
    
    //webbrowsercookies.h 
    namespace WebBrowserStuff{
      	...	//与cookies相关的便利函数
    }
    //以上头文件的代码全部纳入同一名空间
    

    将所有便利函数放在多个头文件内但隶属于同一个命名空间,意味用户可以轻松拓展这一组便利函数。他们需要做的就是添加更多非成员非友元函数到此命名空间内。如现在要添加与图像相关的便利函数:

    //webbrowserimage.h 
    namespace WebBrowserStuff{
      	...	//与图像相关的便利函数
    }
    

    新函数就像其它旧有的便利函数那样可用且整合为一体。这是类无法提供的一个性质,虽然用户可以使用继承来建立派生类,但派生类无法访问基类中的 private 成员。

    Note:

    • 宁可用非成员非友元函数替代成员函数,可以增加封装,包装弹性,功能可扩展性。

    条款24:若所有参数皆需类型转换,请为此采用非成员函数

    展开全文
  • 当运算符重载函数作为成员函数实现:最左边的操作数必须是运算符的一个类对象或者是对该类对象的一个引用。 当运算符重载函数作为友元函数实现:当访问类的private或protected数据成员时必须指定为友元函数。 ....

    当运算符重载函数作为成员函数实现:最左边的操作数必须是运算符的一个类对象或者是对该类对象的一个引用。函数的参数比原来的操作数个数少一个(后置的++、--除外,需要一个int形参),因为第一个操作数会被作为函数调用的目的对象,因此无需出现在参数表中,函数题可以直接访问第一个操作数的成员。
    在这里插入图片描述
    在这里插入图片描述

    当运算符重载函数作为友元函数实现:当访问类的private或protected数据成员时必须指定为友元函数。参数个数与原操作数个数相同,运算符的所有操作数必须显示通过参数传递。
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • C++笔记--关于友元函数和静态成员函数 今天在写程序时用到了好多静态成员函数,然后突然想到了友元函数,有些思考。 首先,两者都可以读写对象的成员变量。基于此可以认为静态函数和友元函数都具有访问类内部数据的...
  • 友元与静态成员

    2020-12-19 09:07:24
     在C++中友元函数允许在类外访问该类中的任何成员,就像成员函数一样,友元函数用关键字friend说明.友元函数可以通过对象访问所有成员,私有和保护成员也一样. 2.1.1将非成员函数声明为友元函数 定义一个类: class...
  • 一、友元函数友元函数是一种特殊的函数,它需要在类体内进行说明,可以访问类的私有成员和保护成员,但又不是...归纳起来,友元函数是一种能够访问类中私有成员的非类成员函数友元函数在定义上和调用上普通函数...
  • 1)友元函数是个函数,只要让普通函数func声明为类A的友元函数,那么func这个函数就能访问类A的所有成员(成员变量、成员函数),无论是public,private,protected 2)由于友元函数不属于类成员,所以友元函数的...
  • 这里写目录标题1. 前言2. 友元函数3. 友元类4. 友元成员函数 1. 前言 友元,一种定义在类外部的普通...通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。 用例子说明: //原始类声明 class COrig
  • 重载操作符重载,使得程序表达更加直观,...对于单目运算符,建议采用成员函数。双目运算符=只能重载为成员函数;单目运算符()、[]、->只能重载为成员函数。第一个操作数只能为ostream类型,所以运算符也只能为友员。
  • C++中的友元函数

    2021-05-13 02:49:54
    具体说:为了使其他类的成员函数直接访问该类的私有变量。即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。实际上具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些...
  • 如果在某个类的定义中用friend声明了一个外部函数(或者是其他类的成员函数,既可以是public型,也可以是private型)后,这个外部函数称为类的友元函数。 C++提供一种允许外部类和函数存取类的私有成员和保护成员的...
  • 一、友元介绍我们知道,类的成员函数可以访问同类的...友元函数友元类二、友元函数友元函数在类作用域外定义,但它需要在类体中进行说明为了该类的成员函数加以区别,定义的方式是在类中用关键字friend说明该函数...
  • 借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。friend 的意思是朋友,或者说是好友,好友的关系显然要比一般人亲密一些。我们会对好朋友敞开心扉,倾诉自己的...
  • 私有成员对于类外部的所有程序部分而言都是隐藏的,访问它们需要调用一个公共成员函数,但有时也可能会需要创建该规则的一项例外。友元函数是一个不属于类成员的函数,但它可以访问该类的私有成员。换句话说,友元...
  • 友元函数和友元类

    2021-05-26 22:40:49
    1.友元函数可访问类的私有和保护成员,但不是类的成员函数 2.友元函数不能用const修饰 3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制 4.一个函数可以是多个类的友元函数 在类的定义中用friend声明了...
  • 有时候有一个外部函数就是需要访问,为了解决这个问题,c++开了个后门,就是友元函数友元函数就是将外部函数在类中进行申明,声明时前面添加friend关键字,将其声明为类的友元函数后就可以任意访问类中成员。...
  • //-- 声明类B是类A的友元类,则B可以访问类A的所有成员了。 friend class B; private: //public: int data; }; class B { public: void callBAF(int i, A& a){ a.data = i; std::cout << "a.data...
  • 运算符重载为成员函数时不同的是,重载的友元函数不属于任何类,运算符的操作数都需要通过函数的形参表传递。操作数在形参表中从左到右出现的顺序就是用运算符写表达式时操作数的顺序。 这里也分双目运算符和单目...
  • C++友元函数的定义和使用 <C++析构函数C++友元类> 类的封装性实现了数据隐藏,即类的私有成员在该类的作用域之外是不可见的。但有时可能需要在类的外部访问类的私有成员,为此 C++ 提供了一种允许类外的函数...
  • 1.静态成员的使用 代码: #include<iostream> using namespace std; class Time { public: static int totalTime; Time(int a,int b,int c); void ShowTime() { cout<<"hour:"<<hour<<...
  • C++ 友元函数

    2021-01-06 21:13:17
    友元函数是在类中用关键字friend修饰的非成员函数友元函数可以是一个普通的函数,也可以是其他类的成员函数,虽然它不是本类的成员函数,但是在它的函数体中可以通过对象名访问类的私有和保护成员。 #include <...
  • 私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。C++是从结构化...
  • c++友元类和友元函数

    2021-05-06 16:10:28
    友元函数不属于类的成员函数,但是友元函数必须在类内部定义; 友元函数使用friend关键词声明; 友元函数能够实现类之间的数据共享,较少系统开销,提高效率,但是会破坏类的封装机制; class FriendFunc { public:...
  • 继承的是:接口 + 缺省实现 (default implementation)非虚成员函数 =>继承的是:接口 + 强制实现 (mandatory implementation)2) 不要重新定义一个继承自基类的非虚函数(never redefinean inherited ...
  • 就是把一个类的成员函数设置成另一个类的友元函数,以便访问这个类的成员函数访问那个类的私有成员。 #include <iostream> #include<string> using namespace std; class building;//前向引用声明 class...
  • 缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数。 B类中嵌A类对象,但是B的成员函数无法直接访问A的私有成员 1.某类中嵌套了一个类,该类普通成员函数可以直接访问 2.普通...
  • 友元函数

    2021-03-09 07:47:34
    请设计一个学生类student,学号、本次考试成绩是其私有数据成员,同时有一个计算本次考试平均成绩的友元函数 double average(student *p,int count)以上类名和友元函数的形式,均须按照题目要求,不得修改。...
  • 友元函数 需要友元解决的问题: 运用operator<<进行函数重载,需要输出,若把operator<<定义为成员变量函数,因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,964
精华内容 15,985
关键字:

友元函数与成员函数的联系