【C++快速上手】番外篇二、知识点总结(持续更新...)
【摘要】
一、重要概念
类访问修饰符
详细参考:【C++快速上手】十七、类访问修饰符(总结)
类访问修饰符有三个:public、private、protected在不同类型的类中,访问不同的修饰符所...
一、重要概念
类访问修饰符
- 类访问修饰符有三个:
public、private、protected
- 在不同类型的类中,访问不同的修饰符所修饰的成员权限,如下表所示:
类的类型 | 访问public修饰的成员 | 访问private修饰的成员 | 访问protected修饰的成员 |
---|---|---|---|
基类 | yes | yes | yes |
派生类 | yes | no | yes |
外部类 | yes | no | no |
- 派生类访问基类中的成员变量只要是
public
或protected
直接写就行,跟访问自己的类一样
继承、重载和多态
- 继承:依据已有的类来定义一个新类,已有的类称为基类(父类),新类称为派生类(子类)。
- 多继承即一个子类可以有多个父类,它继承了多个父类的特性。C++ 类可以从多个类继承成员。
- 重载(类内):是同名不同参,调用时根据参数的不同决定调用哪一个函数。
- 多态(类间):是同名同(或不同)参数,调用时根据函数类型是虚函数还是普通成员函数决定调用哪一个。
- 有继承关系,且使用的是基类的指针指向子类的实例(对象),示例如下:
Shape *shape;
Rectangle rec(10,7);
shape = &rec;
- 1
- 2
- 3
- 4
构造函数与析构函数
- 构造函数只有
1
个参数(或虽然有多
个参数,但只有1
个参数没有默认值)时,最好加上explicit
,避免隐式转换。- 原则上应该在所有的构造函数前加explicit关键字,当你有心利用隐式转换的时候再去解除
explicit
,这样可以大大减少错误的发生。
- 原则上应该在所有的构造函数前加explicit关键字,当你有心利用隐式转换的时候再去解除
- 析构函数最好写成虚函数
virtual
c++
中有这样的约束:执行子类构造函数之前,一定会执行父类的构造函数;同理,执行子类的析构函数之后,一定会执行父类的析构函数,这也是为什么我们一直建议类的析构函数写成虚函数的原因。- 参考《【C++快速上手】七、纯虚函数和抽象类学习笔记》中的“构造函数不能是虚函数,而析构函数可以是虚析构函数”
虚函数
详细参考:
- 虚函数是在基类中使用关键字
virtual
声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。 - 纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它,通过声明中赋值0来声明纯虚函数!
- 纯虚函数即没有函数体的虚函数
- 抽象类:包含纯虚函数的类,不能创建对象。
- 抽象类只能作为基类来派生新类使用,不能创建抽象类的对象,可以创建抽象类的指针和引用。
- 在抽象类中,成员函数内可以调用纯虚函数,在构造函数和析构函数内部不能使用纯虚函数。
- 如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽象类。
- 重要知识点
- 纯虚函数使一个类变成抽象类
- 抽象类类型的指针和引用通常指向派生类的对象
- 如果我们不在派生类中完全覆盖纯虚函数,那么派生类也会变成抽象类。
- 抽象类可以有构造函数
- 构造函数不能是虚函数,而析构函数可以是虚析构函数。
- 当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。如果析构函数不是虚拟的,则只能调用基类析构函数。
②、【C++快速上手】八、C++虚函数的vptr与vtable学习笔记:
-
C++的动态多态性是通过虚函数来实现的;为了实现虚函数,C ++使用一种称为虚拟表的特殊形式的后期绑定
-
每个使用虚函数的类(或者从使用虚函数的类派生的类)都有自己的虚拟表(
vtable
) -
编译器还会添加一个隐藏指向基类的指针,我们称之为
vptr
-
类指针调用函数通常使用
->
操作符;引用调用函数通常使用.
操作符。 -
两种实例与调用函数的方法
- 通过指针:
Base *pt = new Derived();
,调用时通常是:pt->fun1();
这样的形式- 使用
new
创建对象是创建在堆中的,必须要程序员手动的去管理该对象的内存空间。
- 使用
- 直接实例:
Base base
,调用时通常是:pt.fun1();
这样的形式- 不使用
new
创建对象时,对象的内存空间是在栈中的,其作用范围只是在函数内部,函数执行完成后就会调用析构函数,删除该对象。
- 不使用
- 通过指针:
-
C++的动态多态性是通过虚函数来实现的。简单的说,通过
virtual
函数,指向子类的基类指针可以调用子类的函数。例如,上述通过基类指针指向派生类实例,并调用虚函数,将上述代码简化为:
Base *pt = new Derived(); // 基类指针指向派生类实例
cout<<"基类指针指向派生类实例并调用虚函数"<<endl;
pt->fun1();
- 1
- 2
- 3
- 其过程为:
- ①、首先,程序识别出
fun1()
是个虚函数; - ②、其次,程序使用
pt->vptr
来获取Derived
的虚拟表; - ③、最后,它查找
Derived
虚拟表中调用哪个版本的fun1()
。这里就可以发现调用的是Derived::fun1()
。因此pt->fun1()
被解析为Derived::fun1()
!
- ①、首先,程序识别出
二、关键字
explicit 关键字
explicit
关键字只能用于修饰只有一个参数的类构造函数,它的作用是表明该构造函数是显式的,而非隐式的,跟它相对应的另一个关键字是implicit
,意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式)
。explicit
修饰构造函数时,可以防止隐式转换和复制初始化explicit
修饰转换函数时,可以防止隐式转换,但按语境转换除外- 单参数(或虽然有多个参数,但只有1个参数没有默认值)的构造函数最好声明为
explicit
。
-
在基类中将被重写的成员函数设置为虚函数,其含义是:当通过基类的指针或者引用调用该成员函数时,将根据指针指向的对象类型确定调用的函数,而非指针的类型。
- https://blog.csdn.net/u010802169/article/details/88537490
- 只需将基类中的成员函数声明为虚函数即可,派生类中重写的virtual函数自动成为虚函数;
未将test()函数设置为虚函数前的执行结果:
将test()函数设置为virtual后,执行结果如下:
-
基类中的析构函数必须为虚函数,否则会出现对象释放错误。以上例说明,如果不将基类的析构函数声明为virtual,那么在调用delete p2;语句时将调用基类的析构函数,而不是应当调用的派生类的析构函数,从而出现对象释放错误的问题。
-
含有纯虚拟函数的类称为抽象类,它不能生成对象。
-
纯虚函数用来规范派生类的行为,即接口。
文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。
原文链接:recclay.blog.csdn.net/article/details/108036363
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)