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<iostream>
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.4.2 代码示例2(成员函数友元)

#include<iostream>
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.4.3 代码示例3(类友元)

#include<iostream>
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.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.6 总结

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

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

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

2. 基于范围的for循环

for循环新用法

#define _CRT_SECURE_NO_WARNINGS
#include"stdio.h"
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<vector>
#include<map>
#include<list>
using namespace std;
int main()
{
    int ar[] = { 12, 23, 34, 45, 56, 67, 78, 89 };//如果容器不是内置类型,自动识别每个类型

    for (auto& x : ar)//将ar里面的值拷贝到x里,如果为对象,则为引用
    {
        cout << x << endl;
    }
}

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;
}

3.3 静态数据成员属性

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

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

在这里插入图片描述

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

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

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

#include<iostream>
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;
}

[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;
};
#include<iostream>
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();
}

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

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

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

3.6 静态方法

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

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值