C++面试笔记(2)
11 explicit 显式构造函数
explicit修饰的构造函数可用来防止隐式转换
class Test1
{
public:
Test1(int n) // 普通构造函数
{
num=n;
}
private:
int num;
};
class Test2
{
public:
explicit Test2(int n) // explicit(显式)构造函数
{
num=n;
}
private:
int num;
};
int main()
{
Test1 t1=12; // 隐式调用其构造函数,成功
Test2 t2=12; // 编译错误,不能隐式调用其构造函数
Test2 t2(12); // 显式调用成功
return 0;
12.C++ 虚函数 重载 覆盖之间的区别
C++ 虚函数 重载 重写的区别
多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数。Cpp多态性是通过虚函数实现的,虚函数允许子类重新定义成员函数。重写的话分为两种:直接重写成员函数,一个是重写虚函数,其中只有重写了虚函数的才体现了Cpp的多态性。
多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定。
最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用 C++ 多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。
13 早绑定与晚绑定
(1)静态多态(早绑定)
函数重载
(2)动态多态(晚绑定)
虚函数:用 virtual 修饰成员函数,使其成为虚函数
注意:
普通函数(非类成员函数)不能是虚函数
静态函数(static)不能是虚函数
构造函数不能是虚函数(因为在调用构造函数时,虚表指针并没有在对象的内存空间中,必须要构造函数调用完成后才会形成虚表指针)
14 虚析构函数
虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象
lass Shape
{
public:
Shape(); // 构造函数不能是虚函数
virtual double calcArea();
virtual ~Shape(); // 虚析构函数
};
class Circle : public Shape // 圆形类
{
public:
virtual double calcArea();
...
};
int main()
{
Shape * shape1 = new Circle(4.0);
shape1->calcArea();
delete shape1; // 因为Shape有虚析构函数,所以delete释放内存时,先调用子类析构函数,再调用基类析构函数,防止内存泄漏。
shape1 = NULL;
return 0;
}
15 虚函数与纯虚函数
C++ Primer--虚函数与纯虚函数的区别
定义一个函数为虚函数,是为了允许用基类的指针调用子类的这个函数
定义一个函数为纯虚函数,才代表子类没有被实现
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
含有纯虚函数的类为抽象类
任何构造函数之外的非静态函数都可以是虚函数
16. 虚函数的底层实现?虚函数表?虚函数指针?
简述C++虚函数作用及底层实现原理
虚函数的作用:简单讲即实现了多态
基类定义了虚函数,子类可以重写该函数,当子类重新定义了父类的的虚函数后,父类指针根据赋给它的不同的子类指针,动态调用属于子类的该函数,且这样的函数调用是无法在编译器期间确认的,而是在运行期间确认,也叫晚绑定。
底层实现原理:C++对象模型
(1) 每个class产生一堆指向虚函数的指针,放在表格中,这个表格称为虚函数表(vbtl)
(2) 每一个对象被添加了一个指针,指向相关的虚函数表vtbl。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的构造函数,析构函数和拷贝赋值运算符自动完成
(3)
另外,虚函数表地址的前面设置了一个指向type_info的指针,RTTI(Run Time Type Identification)运行时类型识别是有编译器在编译器生成的特殊类型信息,包括对象继承关系,对象本身的描述,RTTI是为多态而生成的信息,所以只有具有虚函数的对象在会生成。
RTTI:运行时的类型识别
程序在运行时能够根据基类的指针或者引用来获得该指针或对象所指向对象的实际类型
-- typeid:运算符返回其表达式或类型名的实际类型
-- dynamic_cast:将基类的指针或者引用安全地准换为派生类型的指针或引用
虚函数指针:在含有虚函数类的对象中,指向虚函数表,在运行时确定
虚函数表:在程序只读数据段,存放虚函数指针,如果派生类实现了基类的某个虚函数,则在许表中覆盖原本基类的那个虚函数指针,在编译时根据类的声明创建
17. 菱形继承?虚继承?虚继承与虚函数比较?
菱形继承和虚继承
菱形继承(钻石问题):
存在问题:浪费存储空间、存在二义性
这时候虚继承就挺身而出,扛下搞定此问题的重担了。虚继承是一种机制,类通过虚继承指出它希望共享虚基类的状态。对给定的虚基类,无论该类在派生层次中作为虚基类出现多少次,只继承一个共享的基类子对象,共享基类子对象称为虚基类。虚基类用 virtual 声明继承关系就行了。这样一来,D 就只有 A 的一份拷贝。
class A
{
public:
A():a(1){};
void printA(){cout<<a<<endl;}
int a;
};
class B : virtual public A
{
};
class C : virtual public A
{
};
class D: public B , public C
{
};
int _tmain(int argc, _TCHAR* argv[])
{
D d;
cout<<sizeof(d);
d.a=10;
d.printA();
}
相同之处:
都利用了虚指针(均占用类的存储空间)和虚表(均不占用类的存储空间)
不同之处:
虚继承
虚基类依旧存在继承类中,只占用存储空间
虚基类表存储的是虚基类相对直接继承类的偏移
虚函数
虚函数不占用存储空间
虚函数表存储的是虚函数地址
18.智能指针
C++ 智能指针简单剖析
智能指针的作用:防止内存泄漏
auto_ptr(C++11中删除了)
shared_ptr:允许多个指针指向同一个对象
unique_ptr:独占所指的对象
weak_ptr: 弱引用,指向shared_ptr所管理的对象
为什么抛弃auto_ptr:避免潜在的内存崩溃
为什么用weak_ptr:解决shared_ptr相互引用时的死锁问题
C++11智能指针
智能指针是一个RAII(Resource Acquisition is initialization)类模型,用来动态的分配内存。它提供所有普通指针提供的接口,却很少发生异常。在构造中,它分配内存,当离开作用域时,它会自动释放已分配的内存。这样的话,程序员就从手动管理动态内存的繁杂任务中解放出来了。
RAII(Resource Acquisition is Intialization)
RAII的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终有效,最后在对象析构时释放资源。
分为常性类型与变性类型
本质:用对象代表资源,把管理资源的任务转换为管理对象的任务
19.强制类型转换运算符
Cpp四种强制类型转换运算符
【Cpp专题】static_cast, dynamic_cast, const_cast探讨
(1) static_cast
- 用于非多态类型的转换
- 不执行运行时类型检查(转换安全性不如 dynamic_cast)
- 通常用于转换数值数据类型(如 float -> int)
- 可以在整个类层次结构中移动指针,子类转化为父类安全(向上转换),父类转化为子类不安全(因为子类可能有不在父类的字段或方法)
向上转换是一种隐式转换。
(2)dynamic_cast
- 用于多态类型的转换
- 执行行运行时类型检查
- 只适用于指针或引用
- 对不明确的指针的转换将失败(返回 nullptr),但不引发异常
- 可以在整个类层次结构中移动指针,包括向上转换、向下转换
(3) const_cast
- 用于删除 const、volatile 和 __unaligned 特性(如将 const int 类型转换为 int 类型 )
(4)reinterpret_cast
- 用于位的简单重新解释
- 滥用 reinterpret_cast 运算符可能很容易带来风险。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。
- 允许将任何指针转换为任何其他指针类型(如 char* 到 int* 或 One_class* 到 Unrelated_class* 之类的转换,但其本身并不安全)
也允许将任何整数类型转换为任何指针类型以及反向转换。 - reinterpret_cast 运算符不能丢掉 const、volatile 或 __unaligned 特性。
- reinterpret_cast 的一个实际用途是在哈希函数中,即,通过让两个不同的值几乎不以相同的索引结尾的方式将值映射到索引。
C++面试笔记(2)的更多相关文章
- Java高级开发工程师面试笔记
最近在复习面试相关的知识点,然后做笔记,后期(大概在2018.02.01)会分享给大家,尽自己最大的努力做到最好,还希望到时候大家能给予建议和补充 ----------------2018.03.05 ...
- php面试笔记(5)-php基础知识-自定义函数及内部函数考点
本文是根据慕课网Jason老师的课程进行的PHP面试知识点总结和升华,如有侵权请联系我进行删除,email:guoyugygy@163.com 在面试中,考官往往喜欢基础扎实的面试者,而函数相关的考点 ...
- php面试笔记(3)-php基础知识-运算符
本文是根据慕课网Jason老师的课程进行的PHP面试知识点总结和升华,如有侵权请联系我进行删除,email:guoyugygy@163.com 在面试中,考官往往喜欢基础扎实的面试者,而运算符相关的考 ...
- php面试笔记(2)-php基础知识-常量和数据类型
本文是根据慕课网Jason老师的课程进行的PHP面试知识点总结和升华,如有侵权请联系我进行删除,email:guoyugygy@163.com 面试是每一个PHP初学者到PHP程序员必不可少的一步,冷 ...
- GitHub标星125k!阿里技术官用3个月总结出的24万字Java面试笔记
最近收到一位粉丝的回馈! 这位粉丝已经成功入职阿里了小编很是羡慕啊! 今天就把这份30w字Java面试笔记给大家分享出来,说来也巧这份资料也是由一位阿里技术官整理出来的这算不算是"搬起石头砸 ...
- 手游2dx面试笔记一
第一轮IQ测试:都来面试程序了,相信IQ再怎么也坑不到哪里去吧.要问什么样的题,几页纸呐, 如:1.找出不同类:羚羊.斑马.鲨鱼 2.在()里添一字使2边都能组词:木()料 3.中间值?:1,2,4, ...
- <转载> C++笔试、面试笔记
这些东西有点烦,有点无聊.如果要去C++面试就看看吧.几年前网上搜索的.刚才看到,就整理一下,里面有些被我改了,感觉之前说的不对或不完善. 1.求下面函数的返回值( 微软) int func(x) ...
- C++面试笔记--树
树 树的题目基本都是二叉树,但是面试官还没有说是不是二叉树的时候千万不要先把答案说出来,要是面试官说是多叉树,而你做的是二叉树就直接挂了! 一. 树的三种遍历.前序.中序.后序,如果直接考遍历,就肯定 ...
- C++面试笔记--继承和接口
整个C++程序设计全面围绕面向对象的方式进行.类的继承特性是C++的一个非常重要的机制.继承特性可以使一个新类获得其父类的操作和数据结构,程序员只需在新类中增加原有类没有的成分. 在面试过程中,各大企 ...
- C++面试笔记--指针和引用
面试一:指针与引用的区别? 答案: (1)非空区别.在任何情况下都不能使用指向空值的引用.因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针 ...
随机推荐
- nrf52832板子焊接后总结的经验
将之前打的nrf52832的板子拿到手了,经过一番焊接和调试后,发现了一些问题,因为是第一次画板焊接调试,很多地方做的不好,现在将自己的一些经验总结如下: 1 在制板之前,丝印层有必要好好的检查,建议 ...
- How to view the DNS address assigned by DHCP
nmcli connection show clear-corporate | grep IP4 IP4.ADDRESS[1]: 101.8.112.9 ...
- 【转】TCP、UDP、RTP(RTCP)区别
转自:https://www.cnblogs.com/imystr/p/4026639.html OSI七层模型OSI 中的层 功能 ...
- ubuntu18.04.2LTS下如何用五笔输入法 --Linux
ubuntu18.04.2LTS下自带五笔输入法,不用去单独下载 1.在设置中找到区域和语言 2.点击加号添加输入源 3.选择,选择「汉语」 4.选择「极点五笔」 开始你的五笔输入法之旅…… 友情链接 ...
- 小程序 新建项目底部tabbar
在app.json中配置 { "pages": [ "pages/index/index", "pages/staging/staging" ...
- vue中<select>绑定事件
<div id="app"> <select v-model="selectItem" @change="selectFn($eve ...
- A*算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- linux逻辑卷管理(LVM)
1. 逻辑卷(LVM)的原理 LVM(Logical Volume Manager)逻辑卷管理 是在物理磁盘和文件系统的之间添加一个逻辑层,通过对底层物理磁盘的封装,以逻辑卷的方式呈现给上层应用,通过 ...
- Jenkins自动构建gitlab项目(jenkins+maven+giltlab+tomcat)
环境准备: System:CentOS 7.3 (最小化安装) JDK: 8u161 (1.8_161) tomcat: 8.5.29 Jenkins: Jenkins 2.107.1 Gitlab: ...
- git命令简介
git作为版本控制器,多分支功能能够很好的协同开发.其中分支中分为主分支和辅助分支 主分支包括:master分支和develop分支,不多做解释 辅助分支包括一下三种分支,其中 需求分支(Featur ...