Week5(Boolan)

关于vptr和vtbl

父类有虚函数,子类也必定有,并且含有自己的虚指针(vptr)。虚指针指向虚表(vtbl),虚表中存放函数指针,指向虚函数所在位置。父类和子类的同名成员函数完全无关联,是不同的函数。子类override的父类虚函数,拥有与父类不同的函数指针。

静态绑定与动态绑定

c语言中的函数调用(call)是静态绑定(static binding),调用函数时总是由编译器解析成固定地址然后跳转,调用结束再跳转回初始的地址。

c++中通过指针调用虚函数是动态绑定,访问虚指针指向的虚表中含有的多个函数地址。


让编译器理解成动态绑定(*p->vptr[n]) (p);得符合三个条件:

1.通过指针调用

2.指针是upcast向上转型 *A pa = new B A是B的父类

3.调用的是虚函数


虚函数的两种用法:

1.template method 通过子类对象调用父类函数,将子类对象的地址(this pointer)作为参数传给父类函数(所有类的成员函数都有隐含的this pointer作为参数),在执行过程中遇到子类中特有的成员函数时跳转到子类,调用结束后又返回继续执行父类函数,正是利用了动态绑定的特性

2.多态   声明容器中的指针时必须指向父类,在使用时可以让它指向子类


关于const

不能由const对象调用non-const函数(不保证data members不变):

const String str(“hello world”);

str.print();

虽然const版本函数也可以被non-const object调用,但当成员函数的const和non-const版本同时存在,const object只能调用const版本,non-const object只能调用non-const版本

array new

array new时,数组的内存除了(元素个数*每个元素的大小)外,还有一个大小为4字节的数用来记录数组元素个数,使数组作为一个整体被分配内存,并且使编译器快速得知构造以及析构函数需要被调用的次数。

绕过自己重载的构造以及析构函数,强制使用默认的全局函数的方法:

Foo* p = ::new Foo(7);

::delete p;

Foo* pArray = ::new Foo[5];

::delete []pArray;

重载placement new:

可以为operator new()写出多个版本,但每个版本的声明必须有独特的参数列(或者类型不同,或者参数个数不同),其中第一参数必须是size_t,其余参数以new()括号中指定的placement arguments为初值。

也可以重载class member operator delete()并写出多个版本(参数列表与operator new对应,即使并未一一对应,也不会报错,意味着放弃处理ctor发出的异常),但只有当new所调用的ctor抛出exception,才会调用重载版的operator delete()。它主要用来归还未完全创建成功的对象所占的内存。

你可能感兴趣的:(Week5(Boolan))