• c++学习之友元


            最近工作好累呀,晚上总是失眠,自学c++的步骤都放慢了,本来之前看c++ primer的,结果这本书讲的太细节了,初学者不是很好把握。所以我又重新找了个教程,比较适合初学者。今天学习到友元函数和友元类了。

            面向对象讲究的是封装,针对封装程度,我们将封装分为private,protected,public,分别对应了三种不同的访问权限。private的成员,仅在对象内部是可以访问的。protected是在该对象内部以及子类中可以使用。public是任意访问。但是有时候也会需要在其他类或函数中来访问private或protected的成员,因此友元有了市场。

            友元的英文是friend,由于c++并不是完全的面向对象语言,因此函数未必就是对象中的一部分,so...友元的使用就分为友元函数和友元类了。

    友元函数

    定义:friend returntype function_name(class); 不过该函数的声明,需要在class类中来进行。注意,在类中定义的函数,如果前面加了friend标志,则说明该函数并不是该类的成员函数,而是友元函数。

            我写了个例子。请参考:

    class Tangle
    {
    private:
    	int x;
    	int y;
    public:
    	Tangle(int,int);
    	Tangle();
    	~Tangle();
    	int print();
    	friend Tangle doubled(Tangle);
    };

            类的实现如下:

    Tangle::Tangle(int a,int b)
    {
    	x = a;
    	y = b;
    }
    Tangle::Tangle()
    {
    	x = 1;
    	y = 1;
    }
    Tangle::~Tangle()
    {
    }
    
    int Tangle::print()
    {
    	cout << "x = " << x << endl;
    	cout << "y = " << y << endl;
    	return 0;
    }
    
    Tangle doubled(Tangle t)
    {
    	Tangle ta;
    	ta.x = t.x *2;
    	ta.y = t.y *2;
    	return ta;
    }


            注意哦....上面的doubled()函数可不是Tangle类的成员函数哦。。。从该函数的实现来看,就知道了。前面根本没有作用域的符号::。

            写个测试main方法:

    int main()
    {
    	
    	Tangle ta1;
    	Tangle ta2(12,21);
    	ta1.print();
    	ta1 = doubled(ta2);
    	ta1.print();
    	return 0;
    }

            该方法就是定义两个对象ta1,ta2,将ta2的成员变量通过构造函数赋值,然后通过友元函数直接来操作ta1的成员变量。通过我们定义的友元函数的逻辑,就可以知道,ta1.x = ta2.x *2,ta1.y = ta2.y*2。因此结果就很明显了。运行结果如下:

             


    友元类

            我们在上面代码的基础上,再定义一个类,毕竟友元类是一种关系么,关系的存在是要有关系双方的。

    class Ctangle
    {
    private:
    	int x;
    	int y;
    public:
    	Ctangle();
    	~Ctangle();
    	friend class Tangle;
    };


            从上面的声明中,我们将Tangle类定义为Ctangle类的友元类,也就是说在Tangle类中可以访问Ctangle类的私有变量。看看Ctangle类的实现吧,我们此处仅用定义Ctangle类的私有变量即可。

    Ctangle::Ctangle()
    {
    	x = 100;
    	y = 200;
    }
    Ctangle::~Ctangle()
    {
    	cout << "ctangle destruct..." << endl;
    }
    


            在Tangle类中声明一个函数来操作Ctangle类。

    class Tangle
    {
    private:
    	int x;
    	int y;
    public:
    	Tangle(int,int);
    	Tangle();
    	~Tangle();
    	int print();
    	void print(Ctangle);
    	friend Tangle doubled(Tangle);
    };

            Tangle类的实现如下:

    Tangle::Tangle(int a,int b)
    {
    	x = a;
    	y = b;
    }
    Tangle::Tangle()
    {
    	x = 1;
    	y = 1;
    }
    Tangle::~Tangle()
    {
    }
    
    int Tangle::print()
    {
    	cout << "x = " << x << endl;
    	cout << "y = " << y << endl;
    	return 0;
    }
    //Tangle类的友元函数
    Tangle doubled(Tangle t)
    {
    	Tangle ta;
    	ta.x = t.x *2;
    	ta.y = t.y *2;
    	return ta;
    }
    //Tangle类中来操作Ctangle类的函数
    void Tangle::print(Ctangle ct)
    {
    	cout << ct.x << endl;
    	cout << ct.y << endl;
    }


            测试的main函数如下:

    int main()
    {
    	Ctangle ct;
    	Tangle t(1,2);
    	t.print(ct);
    	return 0;
    }

            Ctangle类默认的构造函数将该类对象的私有变量初始化为100,200.我们定义一个tangle类来打印ctangle类中的私有成员。


                    

            至此,我们通过ctangle类的友元类来打印了ctangle类的私有变量。此出仅仅举个例子说明,ctangle类的友元类,是可以访问ctangle类的私有成员的。

            另外,还需要说明一点的是友元函数并不是相互的,比如说这里的例子,tangle类可以访问Ctangle类中的私有变量,而Ctangle类却不能访问Tangle类中的私有变量。

    参考代码

            将这篇文章完整的代码放在下面吧。


    #include <iostream>
    using namespace std;
    
    
    class Ctangle;
    
    class Tangle
    {
    private:
    	int x;
    	int y;
    public:
    	Tangle(int,int);
    	Tangle();
    	~Tangle();
    	int print();
    	void print(Ctangle);
    	friend Tangle doubled(Tangle);
    };
    
    
    class Ctangle
    {
    private:
    	int x;
    	int y;
    public:
    	Ctangle();
    	~Ctangle();
    	friend class Tangle;
    };
    
    Ctangle::Ctangle()
    {
    	x = 100;
    	y = 200;
    }
    Ctangle::~Ctangle()
    {
    	cout << "ctangle destruct..." << endl;
    }
    
    
    
    
    Tangle::Tangle(int a,int b)
    {
    	x = a;
    	y = b;
    }
    Tangle::Tangle()
    {
    	x = 1;
    	y = 1;
    }
    Tangle::~Tangle()
    {
    }
    
    int Tangle::print()
    {
    	cout << "x = " << x << endl;
    	cout << "y = " << y << endl;
    	return 0;
    }
    
    Tangle doubled(Tangle t)
    {
    	Tangle ta;
    	ta.x = t.x *2;
    	ta.y = t.y *2;
    	return ta;
    }
    
    void Tangle::print(Ctangle ct)
    {
    	cout << ct.x << endl;
    	cout << ct.y << endl;
    }
    
    int main()
    {
    	
    	/**
    	Tangle ta1;
    	Tangle ta2(12,21);
    	ta1.print();
    	ta1 = doubled(ta2);
    	ta1.print();
    	**/
    
    	Ctangle ct;
    	Tangle t(1,2);
    	t.print(ct);
    	return 0;
    }








  • 相关阅读:
    关于使用quartz动态增删改定时任务
    关于chrome被篡改主页修复方法
    关于git被误删除的分支还原问题
    mysql数据库备份bat脚本
    同步数据库bat脚本
    读取spring boot项目中resource目录下的文件
    使用Java进行udp-demo编程时碰到的consumer和producter无法连接并报出“java.net.SocketException: Can't assign requested address”问题
    关于在项目中遇到MySQL数据库死锁的问题
    Gitlab仓库搭建及在Linux/windows中的免密使用
    GIT
  • 原文地址:https://www.cnblogs.com/pangblog/p/3241365.html
Copyright © 2020-2023  润新知