• C++ 9:友元,范围for,静态成员



    1. 友元

    1.1 友元的定义

    • 友元 friend机制允许一个类授权其他的函数访问类产生 对象 的非公有成员。

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

    1.2 友元的分类

    • 外部函数友元
    • 成员函数友元
    • 类友元(模板类的友元函数)

    1.3 友元的特点

    1. 不具有对称性、:A是B的友元,并不意味着B是A的友元。

    2. 不具有传递性︰A是B的友元,B是C的友元,但A不是C的友元。

    3. 不具有继承性: Base类型继承Object类型,如果Object类型是A的友元,但Base类型不是A友元。

    1.4 输入输出流

    • istream-输入流(标准输入设备cin);
    • ostream-输出流(标准输出设备cout);
    • (错误输出cerr);
    • ifstream-文件输入流;
    • ofstream-文件输出流.

    1.4.1 代码示例1(外部函数友元)

    #include
    using namespace std;
    class Int
    {
    private:
    	int value;
    public:
    	int& Value()
    	{
    		return value;
    	}
    	const int& Value() const
    	{
    		return value;
    	}
    public:
    	Int(int x = 0) :value(x) {}
    	//将输出流函数变为Int类型的友元函数,所以输出流函数可以访问Int类型的私有成员
    	ostream& operator<<(ostream& out) const
    	{
    		out << value;
    		return out;
    	}
    	istream& operator>>(istream& in)//注意:不能加const,加const就不能改变了
    	{
    		in >> value;
    		return in;
    	}
    	friend ostream& operator<<(ostream& out, const Int& it);
    };
    //重载输出流对象
    ostream& operator<<(ostream& out, const Int& it)
    {
    	out << it.value;
    	return out;
    }
    //重载输入流对象
    istream& operator>>(istream& in, Int& it)
    {
    	it >> in;
    	return in;
    }
    int main()
    { 
    	Int a, b;
    	a.Value() = 100;
    	cout << a << " " << b << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    运行结果
    在这里插入图片描述

    1.4.2 代码示例2(成员函数友元)

    #include
    using namespace std;
    class Int;
    class Base
    {
    public:
    	void func(const Int& it);
    };
    
    class Int
    {
    private:
    	int value;
    public:
    	int& Value()
    	{
    		return value;
    	}
    	const int& Value() const
    	{
    		return value;
    	}
    public:
    	Int(int x = 0) :value(x) {}
    
    	friend void Base::func(const Int& it);
    };
    void Base::func(const Int& it)
    {
    	cout << it.value << endl;
    }
    int main()
    {
    	Int a(10);
    	Base base;
    	base.func(a);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    运行结果
    在这里插入图片描述

    1.4.3 代码示例3(类友元)

    #include
    using namespace std;
    
    class Int
    {
    private:
    	int value;
    public:
    	int& Value()
    	{
    		return value;
    	}
    	const int& Value() const
    	{
    		return value;
    	}
    public:
    	Int(int x = 0) :value(x) {}
    
    	friend class Base;//类友元:Base变为了Int的友元,Base可以访问Int所产生对象的所有成员
    };
    class Base
    {
    public:
    	void func(const Int& it);
    	void show(const Int& it);
    };
    int main()
    {
    	Int a(10);
    	Base base;
    	base.func(a);
    	base.show(a);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    1.5 外部友元函数

    外部函数友元,友元函数是一个外部函数,没有this指针,不能用const修饰。外部函数作为友元函数时,无this指针。

    class Object
    {
    private:
        int value;
    public:
        Object(int x) :value(x) {}
        friend ostream& operator<<(ostream& out, const Object& obj);
    };
    ostream& operator<<(ostream& out, const Object& obj)
    {
        out << obj.value;//外部对象友元:外部函数无法访问对象私有属性
        return out;
    }
    int main()
    {
        Object obj(10);
        cout << obj << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    1.6 总结

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

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

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

    2. 基于范围的for循环

    for循环新用法

    #define _CRT_SECURE_NO_WARNINGS
    #include"stdio.h"
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;
    int main()
    {
        int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89 };//如果容器不是内置类型,自动识别每个类型
    
        for (auto& x : ar)//将ar里面的值拷贝到x里,如果为对象,则为引用
        {
            cout << x << endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3. 静态成员

    3.1 定义

    static可以修饰类的数据成员,也可以修饰类的函数成员。

    由关键字static修饰类体中成员,成为类静态成员(static class member)。类的静态成员为其所有对象共享,不管有多少对象,静态成员只有一份存于公用内存中。静态数据成员被当作该类类型的全局对象。

    3.2 c语言静态关键字修饰局部变量

    • 静态关键字修饰局部变量,生存期变为.data
    • 当函数调动时,支队静态变量初始化一次
    • 静态局部变量可以采取引用返回
    int fun()
    {
        static int x = 0;//1.静态关键字修饰局部变量,生存期变为.data 2.当函数调动时,支队静态变量初始化一次 3.静态局部变量可以采取引用返回
        int y = 10;
        return x;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.3 静态数据成员属性

    [1] 设计静态数据成员的目的是信息共享和信息交流

    [2] 静态成员在类中声明,在类外进行定义,定义时不添加static关键字,不能在构造函数的初始列表中创建

    在这里插入图片描述

    [3] 在类外访问是共有的,在类的成员函数中静态成员没有this指针

    在这里插入图片描述
    [4] 静态数据是该类所有对象所共有的,可提供同一类型的所有对象之间,信息共享或信息交换的一种方式。

    [5] 静态属性的类型是int,short,char,并且是const,可以在类中直接初始化

    #include
    using namespace std;
    
    class Array
    {
    private:
    	static const unsigned int n = 10;
    	static const int ar[n];
    };
    const int Array::ar[n] = { 1,2,3,4 };
    
    int main()
    {
    	Array a;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    [6] 静态数据成员的类型可以是其所属类而非static数据成员只能被声明为该类的指针

    在这里插入图片描述
    在这里插入图片描述

    3.4 mutable关键字和static关键字

    class Object//编译错误,产生无穷递归
    {
    public:
        int value;
        Object obj;
    };
    class Object//编译错误,obj必须引用已存在的对象
    {
    public:
        int value;
        Object& obj;
    };
    class Object//正确,指针起初没有指向任何对象
    {
    public:
        int value;
        Object *pobj;
    };
    class Object//正确,静态成员不属于对象,构建obj对象只有value,没有内部对象
    {
    public:
        int value;
        static Object obj;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    #include
    using namespace std;
    
    class Int
    {
    private:
    	mutable int value;//如果在类的非静态成员前面加mutable关键字之后,可以不被const限制
    	static int num;
    public:
    	Int(int x = 0) :value(x) {}
    	void fun() const
    	{
    		num += 100;
    		value += 10;//error不允许改变
    	}
    };
    int Int::num = 0;
    int main()
    {
    	Int a;
    	a.fun();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3.5 同全局变量相比,使用静态数据成员有两个优势

    • 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性。

    • 可以实现信息隐藏,静态成员可以是private成员,而全局变量不能。

    3.6 静态方法

    函数成员说明为静态,将与该类的不同对象无关。静态函数成员的调用,在对象之外可以采用下面的方式:类名::函数名对象名.函数名

    与静态数据成员相反,为使用方便,静态函数成员多为公有。
    在这里插入图片描述


  • 相关阅读:
    华为认证 | 考HCIE,真的不需要先考HCIP
    弘辽科技:超级推荐爆款拉新怎么设置?爆款拉新怎么玩?
    聊聊logback的AsyncAppender
    <图像处理> Canny边缘检测
    GoFrame+Vue+ElementUI管理后台源码
    for循环遍历的`form表单组件`rules规则校验失效问题——下拉框选择之后还是报红---亲测有效
    c#关于类,对象的例子实现
    C++:模板初阶
    弘玑Cyclone2022产品发布会:全新上线智能文档处理交互平台——尚书台
    卷积神经网络 图像识别,卷积神经网络车辆识别
  • 原文地址:https://blog.csdn.net/qq_48580892/article/details/125850452