年底了,给自己放了7天假,这7天基本啥也没有学习,今天开始好好学习啦!奋战今年暑期实习、今年秋招。以下都是看侯捷老师视频总结的
目录
引用的深入理解
引用是啥学C++的都知道,那他和指针有何区别?引用不可以更改指向的对象,引用第一次指定一个对象就一直指向这个内存地址了,指针就可以更改指针对象,指向别的内存,都是指向一块内存地址的,看下图。引用本质上也是指针实现的,但是指针在32位程序中字节是4个大小,而引用的字节是和类型字节大小一样的
继承\组合构造函数谁先调用
本质上就是看内存最深部的类,最深的类,他的构造函数先调用,就是这样的UML图。
上面的情况是先调用Base在调用组合类型,在调用组合类的构造函数写个代码验证一下即可
下面的 Component的构造函数是先调用的,他是最深层的,这个好确定
class Component {
public:
Component() {
cout << "Component construct..." << endl;
}
};
class Base {
//Component c;
public:
Base() {
cout << "base construct..." << endl;
}
};
class Derived : public Base {
Component c;
public:
Derived() {
cout << "Derived construct...." << endl;
}
};
转换函数
以前见过,不知道这个叫转换函数,没有返回值类型,int为要重载的类型,const可加可不加,一般最好加上。
operator int()const {
return 2;
}
malloc的内部实现原理
explicit
这个关键字都知道,我以前也能现象到隐式转换的例子,但是今天的例子更加生动形象,更加理解了explicit。像这个例子,有两种转换思路,编译器报错,因为多种可以选
- 4隐式转换成Fraction对象,相加得到一个新的对象
- f转换成double数值,加上4,在隐式转换一个成新的对象
namespace
这个一般我很少用到,不过目的就是防止各部门之间命名冲突,所以各部门使用不同的namespace挺好的
虚函数指针和虚函数表
这俩小东西经常挺人念叨,面试题也经常问,今天终于学习了一下
子类继承父类的虚函数,实则继承的是调用权,子类的对象在内存中头上有一个指针,就是虚函数指针,这个指针指向一个地方,就是虚函数表。如果子类override了父类的虚函数,那么虚函数表记录的函数入口地址也会随之改变。这也是多态实现的原理。根据虚函数表里的地址来进行调用函数
什么时候有虚函数指针和虚函数表?在动态绑定时期,静态绑定的话直接翻译成call指令了。
动态绑定需要满足三点
- 是个指针
- 向上转型,比如Base* b = new Derived();这样的
- 调用的是虚函数
最近对虚函数又有了新的理解来更新一下。
有虚函数的类就会有虚函数指针和虚函数表,虚函数表是在编译期的时候就确定的了,虚函数表里面有type_info和自己类中的虚函数的地址,后面介绍一下type_info。而多态是运行期的,在运行的时候虚函数指针指向一个虚函数表。从而达到多态的效果。type_info大概的作用就是知道这个对象实际上个什么类型。
Dervied2 d;
Base2* b = new Dervied2(d);
cout << typeid(*b).name() << endl;
cout << typeid(b).name() << endl;
delete b;
类函数this指针的位置、虚函数指针何时初始化
this会作为第一个参数被编译器传进去
class A{
public:
void test(){}
//编译器可能扩展为 void test(A* this){}
};
在创建一个类的时候,在构造函数中会自动插入代码this->vptr=__vtbl__XX会虚函数指针会指向一个虚函数表的
在Base的构造函数和析构函数里调用虚函数为什么不能实现多态
因为,子类的构造函数还没有创建完成,this还是残缺的,当调用Base的构造函数\析构函数时,this中的vptr会指向Base的虚函数表,所以在Base的构造函数和析构函数调用虚函数是不会发生多态的