精华内容
下载资源
问答
  • 对友元理解

    2021-10-08 15:51:19
    私有成员:需要该类的成员函数才能私有成员的访问   但如果要通过一个函数去访问私有成员,但这个函数不属于该类里面的函数。 这就是<友元>起到作用 C++不跟C一样,在C里面定义的数据,没有访问规则,可以...

    一、友元

       在类里面有公有成员,私有成员,保护成员。
    公有成员:是既可以在类外访问也可以在类里访问
    私有成员:需要该类的成员函数才能对私有成员的访问
      但如果要通过一个函数去访问私有成员,但这个函数不属于该类里面的函数。
    这就是"友元"起到作用**

    C++不跟C一样,在C里面定义的数据,没有访问规则,可以直接去访问它,但是在C++这门语言里面定义了各种访问权限规则,什么时候可以去访问这个数据,什么时候又不能去访问这个数据这些都有规定,这样使得数据更安全,不容易被破坏,这就是C++其中的封装特性

    而友元呢,破坏了这种数据的隐藏,隐蔽性的特点,数据都是被隐藏在一个安全的地方,而友元就相当于在这个很安全的地方装了一扇窗子,可以通过这扇窗子进去,访问这个数据。

    二、友元函数

    友元函数示例:

    #include <iostream>
    using namespace std;
    class Point
    {
    public:
    	friend Point middle(const Point& a, const Point& b);  //声明middle是Point类的友元函数
    	Point(float a, float b)  : x(a), y(b) {}
    	void printf()
    	{
    		cout << "中点坐标:" << x << "," << y << endl;
    	}
    private:
    	float x;
    	float y;
    };
    //通过middle函数可以直接访问private里面的数据
    //middle这个函数不属于任何类的成员函数
    Point middle(const Point& a, const Point& b)
    {
    	Point c((a.x + b.x) / 2, (a.y + b.y) / 2);
    	return c;
    }
    int main(int argc, char* argv[])
    {
    	Point a(1, 5);
    	Point b(2, 7);
    	middle(a, b).printf();
    	return 0;
    }
    

    如果想在类外去访问该类的private数据成员,就得声明该类外的函数是该类的友元函数,通过声明后的友元函数才能对该类的私有成员进行访问。

    举个现实生活的例子:
    友元友元不就是朋友的关系嘛,我想去你家里面玩,陌生人让进嘛?肯定不让进,去你家玩,肯定是朋友的关系,在这里Point这个类就相当于你的家,middle这个函数相当于这个人,还要知道middle这个人到底是朋友呢还是陌生人呢,就取决于他是否声明的友元,声明了就是朋友,没有声明就是陌生人。

    三、一个类的成员函数是另外一个类的友元

    #include <iostream>
    #include <cstring>
    #pragma warning(disable : 4996 26432 26401 26409 26440 26485 4150)
    using namespace std;
    class Person;
    
    class Spouse
    {
    public:
    	Spouse(const Person& Phu, const Person& Pw);
    	~Spouse() { delete Phusband; delete Pwife; }
    	void Show() const;
    private:
    	Person* Phusband;
    	Person* Pwife;
    };
    
    class Person
    {
    public:
    	friend void Spouse::Show() const;   //声明Spouse类中的Show成员函数是Persou类的友元函数
    	Person(const char* nm, int ag, const char* sx) : age(ag) {
    		strcpy(name, nm);
    		strcpy(sex, sx);
    	}
    	void Show()
    	{
    		cout << name << " " << age << " " << sex << endl;
    	}
    
    private:
    	char name[10];
    	int age;
    	char sex[10];
    };
    
    Spouse::Spouse(const Person& Phu, const Person& Pw)
    {
    	Phusband = new Person(Phu);
    	Pwife = new Person(Pw);
    }
    
    void Spouse::Show() const
    {
    	cout << "丈夫:" << Phusband->name << " " << Phusband->age << " " << Phusband->sex << endl;
    	cout << "妻子:" << Pwife->name << " " << Pwife->age << " " << Pwife->sex << endl;
    }
    
    int main()
    {
    	Person hus("胡强", 33, "男");
    	Person wf("小风", 32, "女");
    	Spouse sp(hus, wf);
    
    	hus.Show();
    	wf.Show();
    	sp.Show();
    	
    	system("pause");
    	return 0;
    }
    

    定义了两个类Spouse和Persou
    在类Spouse前面引用了class Person,因为类Spouse需要用到类Person,而Person在Spouse的后面
    为了解决这个问题,所以在类Spouse前面引用类Serson.
    但注意的是:类提前声明使用的范围是有限的,只有正式声明一个类才能去定义这个类的对象,在类Spouse中数据成员不能直接定义为Persou类的对象
    改为:
    Persou Phusband;
    Persou Pwife;
    就会报错,这是因为正式声明一个类之前,编译器无法确定Persou类需要多大的内存空间,所以对一个类做了提前引用声明后,可以用该类的名字去指向该类的指针变量或对象的引用。因为指针变量和引用本身的大小是固定的。

    这个代码是将Spouse类的成员函数show()
    作为Persou的友元函数,那么可以通过Spouse类中的show()去访问Persou中的数据成员

    四、友元类

    #include <iostream>
    #include <cstring>
    #pragma warning(disable : 26440 26485 26496 4996 4150 26432 26401 26409)
    using namespace std;
    class Person;
    
    class Spouse
    {
    private:
    	Person* pHusband;
    	Person* pWife;
    public:
    	Spouse(const Person& hus, const Person& wf);
    	~Spouse() { delete pHusband; delete pWife; }
    	void Show() const;
    };
    
    class Person
    {
    private:
    	char name[10];
    	int age;
    	char sex[10];
    
    public:
    	friend class Spouse; //声明Phusband是Pwife友元类
    	Person(const char* nm, const int ag, const char* se) : age(ag)
    	{
    		strcpy_s(name, nm);
    		strcpy_s(sex, se);
    	}
    	void Show() const
    	{
    		cout << name << " " << age << " " << sex << endl;
    	}
    };
    
    Spouse::Spouse(const Person& hus, const Person& wf)
    {
    	pHusband = new Person(hus);
    	pWife = new Person(wf);
    }
    
    void Spouse::Show() const
    {
    	cout << "丈夫: " << pHusband->name << " " << pHusband->age << " " << pHusband->sex << endl;
    	cout << "妻子: " << pWife->name << " " << pWife->age << " " << pWife->sex << endl;
    }
    
    int main()
    {
    	Person huf("张强", 18, "男");
    	Person wf("小丽", 17, "女");
    	Spouse sp(huf, wf);
    
    	huf.Show();
    	wf.Show();
    	sp.Show();
    	system("pause");
    	return 0;
    }
    

    如果把以上代码改为:

    #include <iostream>
    #include <cstring>
    #pragma warning(disable : 26440 26485 26496 4996 4150 26432 26401 26409)
    using namespace std;
    class Spouse;
    class Person
    {
    private:
    	char name[10];
    	int age;
    	char sex[10];
    
    public:
    	friend class Spouse; //声明Phusband是Pwife友元类
    	Person(const char* nm, const int ag, const char* se) : age(ag)
    	{
    		strcpy_s(name, nm);
    		strcpy_s(sex, se);
    	}
    	void Show() const
    	{
    		cout << name << " " << age << " " << sex << endl;
    	}
    };
    
    class Spouse
    {
    private:
    	Person pHusband;
    	Person pWife;
    public:
    	Spouse(const Person& hus, const Person& wf) : pHusband(hus), pWife(wf) {}
    	
    	void Show() const;
    };
    
    
    void Spouse::Show() const
    {
    	cout << "丈夫: " << pHusband.name << " " << pHusband.age << " " << pHusband.sex << endl;
    	cout << "妻子: " << pWife.name << " " << pWife.age << " " << pWife.sex << endl;
    }
    
    int main()
    {
    	Person huf("张强", 18, "男");
    	Person wf("小丽", 17, "女");
    	Spouse sp(huf, wf);
    
    	huf.Show();
    	wf.Show();
    	sp.Show();
    	system("pause");
    	return 0;
    }
    

    让Person类在Spouse类的前面 那么在Spouse类中可以直接定义对象
    Person pHusband;
    Person pWife;

    先声明Person类,才能知道Person这个类的大小,才能在Spouse类中定义Person类的对象,编译器才能知道具体要分配多大的内存空间
    如果将friend class Spouse改为:
    friend void Spouse:: Show() const;

    编译器会报错,由于先定义的是Person类,后定义的是Spouse类,如果在先声明的Person类中定义一个Spouse类中的Show函数是Person的友元, 编译器找不到Spouse类中是否存在Show这样的一个函数。

    展开全文
  • 谈谈对友元理解

    2020-04-21 21:52:03
    解决方法就是使用友元函数。友元函数是一种特权函数,c++允许这个特权函数访问私有成员。 friend关键字只出现在声明处。 其他类,类成员函数,全局函数都可以声明为友元友元函数不是类的成员,不带this指针。 ...

    类的主要特点之一就是数据隐藏,即类的私有成员无法在类的外部访问。但是,有时候需要在类的外部访问类的私有成员。解决方法就是使用友元函数。友元函数是一种特权函数,c++允许这个特权函数访问私有成员。
    friend关键字只出现在声明处。
    其他类,类成员函数,全局函数都可以声明为友元。
    友元函数不是类的成员,不带this指针。
    友元函数可访问对象任意成员属性,包括私有属性。
    注意的是:
    友元关系不能被继承
    友元关系是单向的
    友元关系不具有传递性

    展开全文
  • C++友元理解

    2016-08-24 19:52:23
    为了是自己理解深刻,方便自己随时查找,也方便大家,特发此博客共享:直接上代码: /* 为了使类的private成员和protected成员可以被其他类和其他成员函数使用,引入了友元概念。 友元函数:友元是普通函数或类的...

    为了是自己理解深刻,方便自己随时查找,也方便大家,特发此博客共享:直接上代码:

    /*
    为了使类的private成员和protected成员可以被其他类和其他成员函数使用,引入了友元概念。
    友元函数:友元是普通函数或类的成员函数
    友元类:友元是一个类,类的所有成员函数称为友元函数。
    友元函数定义后可以访问该类的所有对象:private,protected,public成员。
    格式:friend<数据类型><友元函数名>(参数表)
    */
    #include<iostream>
    #include<string>
    using namespace std;
    class Rectangle {
    public:
    	Rectangle(double a = 0, double b = 0)//定义构造函数
    	{
    		length = a;
    		width = b;
    	}
    	Rectangle(Rectangle &r); //重载构造函数
    	double getlength() { return length; }
    	double getwidth() { return width; }
    	friend double area(Rectangle &rectangle); //声明外部友元函数
    /* 
    友元函数不是类的成员,所以不能直接引用对象成员的名字,也不能通过this指针引用对象成员,必须通过作为入口参数传递进来的对象名会对象指针来引用该对象成员。
    */
    private:
    	double length;
    	double width;
    };
    double area(Rectangle &rectangle) // 定义友元函数
    {
    	return (rectangle.length*rectangle.width);
    }
    
    /* 友元成员:一个类的成员函数是另一个类的友元函数。不仅可以访问自己类的各个成员,也可以访问友元类的各个成员。
    这种机制使得两个类可以互相访问。
    */
    class boy;
    class girl {
    public:
    	explicit girl(char *n, int a)
    	{
    		name = new char[strlen(n)+ 1];//分配空间
    		strcpy_s(name,sizeof(name), n); //调用字符串拷贝函数
    		age = a;
    	}
    	void prt(boy &b);
    	~girl() { delete name; }
    private:
    	char *name;
    	int age;
    };
    class boy {
    public:
    	explicit boy(char *n, int a)
    	{
    		name = new char[strlen(n) + 1];//分配空间
    		strcpy_s(name, sizeof(name), n); //调用字符串拷贝函数
    		age = a;
    	}
    	friend void girl::prt(boy &b);
    	~boy() { delete name; }
    private:
    	char *name;
    	int age;
    
    };
    void girl::prt(boy &b)
    {
    	cout << "girl\'s name:"<<name<< "  age:" << age << "\n";//直接调用自己类的private成员
    	cout << "boy\'s name:" <<b.name<< "  age:" << b.age << "\n"; //调用友元类的成员
    
    }
    //友元类可以实现类之间的数据共享
    int main()
    {
    	/*Rectangle ob(4, 5);	 //友元函数用例
    	cout << "The area is:" << area(ob)<<endl; */
    
    	girl g1("szu", 15);	//友元成员用例
    	boy b1("Tec", 16);
    	g1.prt(b1);
    
    	system("pause");
    	return 0;
    }


    展开全文
  • 静态成员的理解 在之前的学习过程中我们已经了解到模块数据的共享与保护机制,比如:数据成员对外不公开,对象里定义的变量也具有作用域等等。 对于一个类,函数成员是所有的对象相同的,而数据成员则是各自不同的...

    面向对象程序设计课堂笔记

    对静态成员的理解

    在之前的学习过程中我们已经了解到模块数据的共享与保护机制,比如:数据成员对外不公开,对象里定义的变量也具有作用域等等。

    对于一个类,函数成员是所有的对象相同的,而数据成员则是各自不同的。如果这时候我们引入了一个新的数据成员,对于所有的对象来说,他的值都是相同的,此时再去对每一个对象定义一次此数据成员则显得冗杂。由此,我们引入了静态数据成员。

    根据上一段的解释,可以看出静态数据成员的简单定义:是类共有的数据,类的所有成员都维护这一个数据。

    在代码中这样定义:

    class A{
    	private:
    		int b;///一般数据成员
    		static int exnum;///静态数据成员
    }
    

    对于程序中的模块,都会在内存中占据一定的存储空间,那么静态数据成员exnum又是如何存储的呢?

    因为静态数据成员是类共有的成员,所以他不会占用对象的存储空间。可以结合下面的代码进行理解:

    #include<bits/stdc++.h>
    using namespace std;
    class A{
        private:
            int b;
            static int exnum;
    };
    int main(){
        A a;
        cout<<sizeof(A)<<endl;
        cout<<sizeof(a)<<endl;
        return 0;
    }
    
    

    运行结果如图:

    在这里插入图片描述

    因为int类型的b在内存中占四个字节,也就说明了exnum并没有存储在对象a中。

    具体有关的理解的博客:传送门

    变量在使用前都需要初始化,这个也不例外。初始化的语法如下:

    int A::exnum=0;
    

    其中“::”是预作用符,表示后面的操作对象属于哪个类。

    定义一个东西后,我们需要使用,那么我们如何访问这一成员呢。

    通过之前的学习,我们可以知道下面的方式是可以访问exnum的:

    #include<bits/stdc++.h>
    using namespace std;
    class A{
        private:
            int b;
            static int exnum;
        public:
            A(){exnum=exnum+1;}///构造函数
            void shownum(){cout<<"当前的生存对象个数为:"<<exnum<<endl;}
            ~A(){exnum=exnum-1;}///析构函数
    };
    int A::exnum=0;
    int main(){
        A a;
        a.shownum();
        return 0;
    }
    

    以上方式是通过对象来访问静态成员,这也就说明了对象具有静态成员的访问权。

    但是如果我们还没有构造对象,又该如何访问呢。

    前面静态数据成员的定义已经指明,静态成员属于类,所以我们可以通过通过类名直接访问。理论上如果exnum是public的,这是可行的,但是exnum是私有的数据成员,由于模块的安全性,语法并不支持这种操作。

    这时候我们希望某些函数的调用也不依赖于对象,就可以再引进一个静态函数了,与静态数据成员类似,这一函数也是属于类,由类直接调用。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    class A{
        private:
            int b;
            static int exnum;
        public:
            A(){exnum=exnum+1;}///构造函数
            static void shownum(){cout<<"当前的生存对象个数为:"<<exnum<<endl;}
            ~A(){exnum=exnum-1;}///析构函数
    };
    int A::exnum=0;
    int main(){
        A::shownum();
        return 0;
    }
    

    关于对友元函数的理解都在代码里了~

    作业:

    #include<bits/stdc++.h>
    using namespace std;
    class StaticTest{
    public:
        StaticTest(int x, int y, int z);  ///内联构造函数在类里的定义
    	void ObjectShowInfo(){
    		cout<<"("<<a<<","<<b<<","<<c<<")"<<endl;
    	}
        static void ObjectShowSum(){///静态函数,调用不依赖于对象
        	cout<<"sum="<<sum<<endl;
    	}
        void ShowObjectInfo(StaticTest& s);///内联函数,输出sum值
    
    private:
        int a, b, c;///一般成员,只能通过对象调用
        static int sum; ///静态数据成员,可以通过对象访问,也可以通过类名直接访问
        //sum记录产生的所有对象的数据成员A、B、C之和
    };
    ///内联构造函数
    StaticTest::StaticTest(int x, int y, int z):a(x),b(y),c(z){
        cout<<"构造函数"<<endl;
        sum+=x+y+z;///更新sum的值
    }
    int StaticTest::sum=0;///静态数据成员的初始化,一定不要忘记
    void StaticTest::ShowObjectInfo(StaticTest& s)
    {   //一种是直接操作数据成员输出
       //调用其他函数功能
       //以上两种方式选一
       ///调用函数功能进行成员的输出
        cout<<"调用函数功能进行成员的输出"<<endl;
        s.ObjectShowInfo();
        s.ObjectShowSum();
        cout<<"直接操作进行数据成员的输出"<<endl;
        cout<<s.a<<" "<<s.b<<" "<<s.c<<" "<<s.sum<<endl;
    }
    int main(void)
    {
    	///生成两个对象  M N
        StaticTest m(1,2,3);
        StaticTest n(4,5,6);
    
    	///调用一般成员显示信息
        m.ObjectShowInfo();
        n.ObjectShowInfo();
    
        ///对象调用静态成员显示信息和sum
        m.ShowObjectInfo(m);
        m.ObjectShowSum();
    
        ///类作用域调用静态成员
        StaticTest::ObjectShowSum();
    
        return 0;
    }
    
    /*
    运行结果如下:
    构造函数
    构造函数
    (1,2,3)
    (4,5,6)
    调用函数功能进行成员的输出
    (1,2,3)
    sum=21
    直接操作进行数据成员的输出
    1 2 3 21
    sum=21
    sum=21
    */
    
    
    
    /* 添加友元,float MyDistance( pb,  pe)
     sqrt((pe.x - pb.x) * (pe.x - pb.x) + (pe.y - pb.y) * (pe.y - pb.y));
    */
    
    #include <math.h>
    #include <iostream>
    using namespace std;
    class MyPoint{
    public:
        MyPoint(int ix, int iy):x(ix),y(iy){
            cout<<"构造函数"<<endl;
        }
    
        void print() {
            cout << "(" << x<< "," << y<< ")" << endl;
        }
    
        ///友元之普通函数
        friend double MyDistance( MyPoint& pb,MyPoint&  pe);
    /*
    要注意:如果友元函数时全局函数,直接声明即可
    但如果该友元函数是某个类中的函数,需要加预作用符说明该函数属于哪一类
    */
    private:
        int x;
        int y;
    };
    /*
    友元函数的定义:如果一个类允许某外部函数具有其成员函数的权限
    即可以直接访问类内成员,那么在该类的定义中应当声明此函数为友元函数
    */
    double MyDistance( MyPoint& pb,MyPoint&  pe){
        return sqrt(1.0*(pe.x - pb.x) * (pe.x - pb.x) + 1.0*(pe.y - pb.y) * (pe.y - pb.y));
    }
    int main()
    {
        MyPoint pt1(1, 2);
        MyPoint pt2(1, 4);
        cout << "pt1和pt2之间的距离: " << MyDistance(pt1, pt2) << endl;
        return 0;
    }
    
    
    
    #include <math.h>
    #include <iostream>
    using namespace std;
    /*
    如果想要一个类里的函数都变为另一个类里的友元函数,
    可以直接逐个把其变为友元函数,但这样显得过于繁杂,
    所以我们也可以将该类变为友元类,语法是先在类前加前向声明,
    再在类内定义说明
    */
    
    ///类的前向声明
    class MyLine;
    
    class MyPoint
    {
    public:
        MyPoint(int ix = 0, int iy = 0) :x(ix), y(iy) {cout<<"构造函数"<<endl;}
    
        void print() {
            cout << "(" << x<< "," << y<< ")" << endl;
        }
    
        ///友元类
        friend class MyLine;
    
    private:
        int x;
        int y;
    };
    
    
    class MyLine
    {
    public:
        double MyDistance(MyPoint& pb,MyPoint&  pe){
            return sqrt(1.0*(pe.x - pb.x) * (pe.x - pb.x) + 1.0*(pe.y - pb.y) * (pe.y - pb.y));
        }
    
        void ShowPoint(MyPoint& p){
    	   cout << "(" <<p.x<< "," <<p.y<< ")" << endl;
    	}
    
        void showLine(MyPoint& pb,MyPoint&  pe) {
    	    ShowPoint(pb);
    	    ShowPoint(pe);
    	}
    };
    
    int main(void)
    {
        MyPoint pt1(1, 2);
        MyPoint pt2(3, 4);
    
        MyLine line;
        line.showLine(pt1,pt2);
        cout << "pt1和pt2之间的距离: " << line.MyDistance(pt1, pt2) << endl;
        return 0;
    }
    
    

    完结撒花~

    展开全文
  • c++友元函数和友元类的理解

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

    2020-10-24 17:30:40
    C++友元友元函数友元类   我们知道,一个类中可以有公用的(public)成员和私有的(private)成员,在一个家庭的住宅中,我们可以将客厅比喻为公用部分,因为通常客厅是允许任何来访客人进入的,而卧室则不希望...
  • 今天小编就为大家分享一篇关于在C++中关于友元函数的进一步理解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 友元函数

    2019-04-27 22:56:39
       友元函数是C++中,成员函数或者类外函数访问类里的私有数据成员用的比较方便的函数,友元函数的关键字是friend,我们暂时把它理解成“友好关系”的意思。    我们用两个类来比喻这种关系吧。 二.友元函数...
  • 以前总是friend感到迷茫,其实很简单,自己总结了一下,欢迎交流
  • 友元函数1.1 如何`<< 和 >>`进行重载呢?2.友元类 1.友元函数 友元函数可访问类中的所有成员,但不是该类中的成员函数。 例: class Date { friend void Print(Date& d);//友元函数 public: ...
  • 友元函数和友元

    2018-08-24 16:34:53
    https://www.cnblogs.com/staring-hxs/p/3432161.html
  • 不能重载为类的静态成员应该比较容易理解,因为静态成员函数是属于整个类的,不是属于某个对象的,它只能去操作类静态数据成员。而赋值运算符“=”是基于对象操作的。那么为什么赋值运算符不可以重载为类的友元函数...
  • 目录 一、友元函数 1.非成员函数 2.成员函数 3.友元函数的重载 二、友元类 ...三、友元与封装性 ...C++是从结构化的C语言发展而来的,需要照顾结构化设计程序员的习惯,所以在私有成员可访问范围的...
  • 友元类的理解

    2019-09-28 03:21:45
    借用一下https://www.cnblogs.com/zhuguanhao/p/6286145.html的代码 #include <iostream> using namespace std; class A { public: friend class C; //这是友元类的声明 priva...
  • 友元的特点就是他是普通函数,并不是成员函数。他可以调用这个类的私有成员。 这里有个实际用法: 如上的redisAsyncCommand函数,其中第二个参数为函数指针。 这里不能反成员函数指针。因为成员函数指针里面...
  • NULL 博文链接:https://jacky-dai.iteye.com/blog/2305426
  • 关于友元理解

    2021-07-08 09:36:42
    友元 友元是C++提供的一种破坏数据封装和数据隐藏的机制; 通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息; 可以使用友元函数和友元类; 为了确保数据的完整性,及数据...
  • 但是C++提供了一种辅助手段——定义类的友元。【友元可以访问类的所有成员。友元可以是一个普通函数,成员函数或者另外一个类。】 友元是非对称的,非传递的。除非特别声明。 在一个类A中,如果将关键字friend冠于一...

空空如也

空空如也

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

对友元的理解