文章目录
9. 友元声明 friend
作用:非成员函数访问类中的私有成员
特点:友元关系单向性,友元关系不可传递
该类外的函数和其他类访问私有成员
#include <iostream>
using namespace std;
class Integer{
// 友元声明
friend void Func(Integer& num); // 友元函数:让指定函数可以访问私有内容
friend class Friend; // 友元类:让指定其他类可以访问该类私有内容
public:
Integer(int n):n(n){
} // 初始化列表
void Print(){
cout << n << endl;
}
private:
int n;
};
// 用来打印num
void Func(Integer& num){
cout << num.n << endl;
}
// 定义一个其他类
class Friend{
public:
void Func(Integer& num){
cout << num.n << endl;
}
};
int main(){
Integer num(10);
num.Print();
Func(num);
Friend f;
f.Func(num);
}
结果为:
10
10
10
如何访问类中的私有成员:
- 通过友元声明来获得访问权限
- 通过访问类的地址来获取私有成员的数据
类可以看成结构体,类的大小其实是里面成员变量的大小,成员函数不算
所以,找到该类的地址(n的地址),访问地址的数,就能知道类中私有成员变量的数是多少
内容升级:两个类通过友元相互调用私有成员,用地址来获取私有成员数据
#include <iostream>
using namespace std;
class Friend; // 提前声明,避免不认识
class Integer{
friend void Func(Integer& num); // 友元函数
friend class Friend; // 友元类
public:
Integer(int n):n(n){
} // 初始化列表
void Print();
void Test(Friend& f);
private:
int n;
};
// 访问私有变量的两种方法
void Func(Integer& num){
cout << num.n << endl;
}
void Func2(Integer& num){
cout << *(int*)&num << endl;
}
class Friend{
friend class Integer; // 友元类
public:
void Func(Integer& num);
private:
void Test();
};
// 在外部定义函数
void Integer::Print(){
cout << n << endl;
}
void Integer::Test(Friend& f){
f.Test();
}
void Friend::Func(Integer& num){
cout << num.n << endl;
}
void Friend::Test(){
cout << "Test" << endl;
}
int main(){
Integer num(10);
num.Print();
Func(num);
Friend f;
f.Func(num);
num.Test(f); // 通过Integer类访问Friend类中的私有函数
Func2(num); // 通过地址访问私有变量
}
结果为:
10
10
10
Test
10
10. const 限定符
10.1 const 与变量
const int size = 4;
int const size = 4;
使用 const 应该注意:
- const 变量通常是只读的(不允许修改)
- const 变量定义时,必须初始化
const 与宏定义 #define 的区别:
不同方面 | const | 宏定义 #define |
---|---|---|
编译器处理方式 | 编译运行阶段使用 | 预处理阶段展开/替换 |
类型 | 有具体的类型 | 没有类型 |
安全检查 | 编译阶段会执行类型检查 | 不做任何类型检查 |
存储方式 | 分配内存 | 不分配内存 |
10.2 const 与指针
const int *p1 = 初始值;
int const *p2 = 初始值;
上式指针常量表示:指针指的内容不能改变,指针是可以改变的
int * const p3 = 初始值;
上式常量指针表示:指针所指的地址不能改变,地址里面的内容是可以改变的
指针所指的地址不能改变,所以必须初始化
10.3 const 与引用
const int& f1 = n;
int const& f2 = n;
相当于 f1 和 f2 是 n 的别名
表示:都是引用对象不能改变
10.4 const 与函数的参数和返回值
const 类型参数可以接受 const 变量和非 const 变量
非 const 类型参数不能接受 const 变量,只能接受非 const 变量
对于指针是如此:
// 这里的写不写const会导致接受类型不同
void PrintP(const char* s){
cout << s << endl;
}
char* s1 = "abcd";
PrintP(s1);
const char* s2 = "abcd";
PrintP(s2);
对于引用也是如此:
// 这里的写不写const会导致接受类型不同
void PrintY(const int& n){
cout << s << endl;
}
int m = 10;
PrintY(m);
PrintY(n); // 这里的n是前面定义的const变量
PrintY(20); // 这里的20是const变量
当主函数中传的值是不能改的值时,函数传参接收时必须也要定义为const,不然会报错
10.4 const 与类
类中可能用到 const 的地方:
- 类中定义的成员变量,注意要对变量初始化,用初始化列表的方式
- 类中的成员函数,隐藏参数在接收时会有规律(和上一节的一样)
如果成员函数不修改成员变量,需要在函数后加 const
class Test{