C++类与对象知识点合集:
【C++】类(上):初识类和对象
【C++】类(中):类中的默认成员函数
【C++】类(下):类成员与explicit、const、mutable、volatile、static、friend关键字
目录
- 关键字explicit
- 关键字const
- const修饰变量
- const修饰指针变量
- const修饰引用变量
- const修饰类外函数
- const修饰类成员
- 1. 修饰类的实例对象
- 2. 修饰类的成员变量
- 3.修饰类的成员函数
- 关键字mutable
- 关键字volatile
- 关键字static
- 关键字friend
- 友元函数
- 友元类
关键字explicit
explicit:用来声明类的单参构造函数为显示调用,使其不能隐式转换。
- 作用:消除单参构造函数(或有缺省参数的全参构造函数)的类型转换问题;
implicit
关键字作用和explicit
相反,声明构造函数为隐式调用;- 无参构造函数和多参构造函数默认为显示调用的,单参构造函数默认为隐式调用;
- 隐式调用的构造函数会导致:函数参数会发生类型隐式转换;
const:用来修饰一个变量或对象,约束其值不能被修改。
- 该变量被标记为常量,无法被修改;
- const修饰的变量必须被初始化;
- const 在 * 前,表示常量指针:指向常量的指针
const int* p;
int const* p;
- const 在 * 后,表示指针常量:该指针不能指向其他变量
int* const p;
-
引用变量被标记为常量引用,常量引用不能直接修改被引用的变量;
-
const修饰的引用变量可引用非const类型变量(属于权限缩小,合理):
-
const修饰的引用类型与所引用对象类型不一致:
-
不能直接对函数+const修饰;
-
const修饰函数的参数,表示该参数在函数体内不能修改;
-
const修饰参数的函数不会与普通参数的函数构成重载;
-
const修饰函数返回值;
- 表示该对象是一个常量,不能改变内容;
- 被const修饰的类对象,既不能改变类中的成员变量,也不能调用类中任何非const成员函数;
- const修饰的成员变量不能被修改;
- 只能在初始化列表中被初始化(引用变量也是);
-
const直接修饰成员函数表示此函数不能对任何成员变量进行修改;
本质:修饰的是该成员函数隐含的this指针;
-
静态成员函数不能使用const修饰(没有this指针);
-
为了提高程序安全性,如果成员函数内部不会进行修改元素的 *** 作,那么将该成员函数直接定义为const函数(例如打印函数);
-
四种常见情景:
-
const也可以指修饰成员函数的参数、返回值;
mutable:为了突破const的限制而设置,被mutable修饰的变量,将永远处于可变的状态。
- 可以用在一个const函数中,甚至结构体变量或者类对象为const,其mutable成员也可以被修改
volatile:称为最易变的关键字,其修饰的数据,编译器不可对其进行执行期寄存于寄存器的优化。
一个被const修饰的变量其实并没有直接存储到了静态常量区,只是告诉编译器该变量以标记为常量,不可修改,但其实通过变量指针解引用依旧可以修改该const常量值:
而如果对于一个静态区的变量使用const关键字修饰,就无法通过指针修改其值:
现在来看这段特殊的代码:
#include <windows.h> //使用Sleep函数
int main()
{
const int a = 1;
int* pa = (int*)&a;
int cur = 0;
while (a)
{
if (cur == 5)
{
*pa = 0;
}
cur++;
cout << a << endl;
Sleep(1);
}
return 0;
}
这个代码非常易懂,就是让循环进行5次后,通过指针修改const循环条件变量的值让循环结束,结果应该是循环执行5次:
之所以会出现上面的情况,"罪魁祸首"就是 *** 作系统;
而如果为了上面的const变量加上关键字volatile
,就是告诉OS不要进行优化,而是生成对应代码直接存取原始内存地址,即使是const修饰的变量,这就是最易变关键字volatile
的作用;
这个关键字现实中的使用场景常见于多线程编程中,满足多线程同步、中断、硬件编程等特殊需要,因为一个共享变量可能在当前线程好像是不可修改的,但在其他线程有可能会修改这个值,有了关键字volatile
就可以避免这种bug;
此关键字知识点详见博客:【C++】详谈关键字static
【几点注意事项】:
- static修饰的类成员变量——静态成员变量;
- static修饰的类成员函数——静态成员函数;
- 静态成员属于类而不属于任何对象(因此对象大小不包括);
- 静态成员属于类成员,仍受访问限定符(public、protected、private)的限制;
- 静态成员函数只可以访问静态成员变量(普通函数均可以);
- 静态成员函数不能调用普通成员函数,但可以被其他普通函数调用;静态成员函数只可以调用静态成员函数;
- 静态成员函数无法修饰为const函数(不允许也没意义);
为了提高编程的灵活性和效率,C++提供了friend关键字来实现类的友元函数和友元类。
一个类的成员变量如果被设为private私有权限,那么类外的函数是无法对改成员变量进行访问的(类内成员函数访问类成员不是权限限制);
而友元函数,可以实现非类成员函数,但可以访问类的私有成员变量。
- 友元函数定义在类外,在类内只能声明它的函数原型,并加上friend关键字;
- 友元函数不是成员函数,它是类的朋友;
- 友元函数是类外函数,没有this指针;
- 友元函数可以访问类的全部成员;
- 友元关系是单向的,不具有交换性;
// 测试类
class Test
{
// 声明友元函数
friend void Print(const Test& A);
private:
int _a;
};
// 定义友元函数,无需加friend关键字
void Print(const Test& A)
{
cout << A._a << endl;
}
友元类
在一个类A使用关键字friend
声明类B,那么类B就是类A的友元类。那么类B的成员函数可以访问类A的所有成员;
-
声明位置:公有私有均可,常写为私有(把类看成一个变量);
-
声明: friend + class + 类名(不是对象);
-
类名必须是程序中的一个已定义过的类;
-
友元关系是不能被继承的,就像父亲的朋友未必是儿子的朋友;
-
友元关系是单向的,不具有交换性;
若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明;
-
友元关系不具有传递性;
若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的声明;
class A
{
private:
int _a;
friend class B; // 声明类B为类A的友元类
};
class B
{
public:
void Fun(A& a) //类B可以访问类A的任何成员
{
cout << a._a << endl;
}
};
类和对象
完结撒花 ~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)