文章目录
1. 友元
1.1 友元的定义
-
友元 friend机制允许一个类授权其他的函数访问类产生 对象 的非公有成员。
-
友元声明以关键字friend开头,它只能出现在类的声明中,它们不受其在类体中的public,private和protected区的影响。
1.2 友元的分类
- 外部函数友元
- 成员函数友元
- 类友元(模板类的友元函数)
1.3 友元的特点
-
不具有对称性、:A是B的友元,并不意味着B是A的友元。
-
不具有传递性︰A是B的友元,B是C的友元,但A不是C的友元。
-
不具有继承性: 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 总结
-
友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符"."加对象成员名。但友元函数可以访问类产生对象的所有成员,一般函数只能访问类中的公有成员。
-
友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果一样。
-
某类的友元函数的作用域并非该类作用域。如果该友元函数是另一类的成员函数,则其作用域为另一类的作用域,否则与一般函数相同。
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 静态方法
函数成员说明为静态,将与该类的不同对象无关。静态函数成员的调用,在对象之外可以采用下面的方式:类名::函数名
或对象名.函数名
;
与静态数据成员相反,为使用方便,静态函数成员多为公有。