1、 对象模型:关于vptr(虚函数表指针)和vtbl(虚函数表)
1.1 课堂内容总结
(1)class中有虚函数时,对象中会多一个指针,0x409004,内存会多四字节;
(2)classB继承classA,classB有自己的vfunc1(),有classA的vfunc2(),classC继承classB,classC有自己的vfunc1(),有classB的vfunc2()(也就是classA的vfunc2());
(3)继承是继承的调用权,不是内存大小;
(4)父类有虚函数,子类肯定有虚函数;
(5)子类中函数与父类同名,但不是一个函数。
1.2 课后补充学习
如果一个类包含了一个虚函数,那么编译器就会为该类产生一个虚拟函数表vtbl,该表是类级别的,即该类的所有对象共享同一个vtbl,且向该类的对象中安插一个指针,指向该虚函数表。例如:
class A
{
public:
virtual void foo();
};
A a,b;
那么对象a,b的内存中各有一个vptr,他们的值就是虚函数表的地址。
再考虑下面的情况:class B:public A{ };
那么类B有虚函数表吗?有,而且B的虚函数表和A的虚函数表不一样,也就是说,不同的类有不同的虚函数表。在上面的情况,B的虚函数表中的虚函数地址和A的是一样的,但是还是要为B产生一个虚函数表。
2、对象模型:关于this
2.1 课堂内容总结
(1)将常规的同一不变的放在onfileopen()中,将特殊的放在serialize()中;
(2)CDocument::OnFileOpen(&myDoc)中“&myDoc”为this,当this指子类就符合向上转型(保证安全);
(3)C++中所有成员函数中一定有this参数。
2.2 课后补充学习
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。
例如,调用date.SetMonth(9) <===> SetMonth(&date, 9),this帮助完成了这一转换 。
this的用法:一种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;另外一种情况是当参数与成员变量名相同时使用this指针,如this->n = n (不能写成n = n)。
更多更详细的关于this的介绍见guirenwang的博客:http://blog.csdn.net/guirenwang/article/details/2611355
3、对象模型:关于Dynamic Binding
3.1 课堂内容总结
(1)静态绑定一定是绑定某个地址;
(2)动态绑定的三个条件:通过指针调用,指针是向上转型,调用的是虚函数。
3.2 课后补充学习
对象的静态类型:对象在声明时采用的类型。是在编译期确定的。对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。
静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。
如何区分遗憾语句调用的是否为同一个函数,详见常高伟的博客:http://blog.csdn.net/chgaowei/article/details/6427731
4、const
对于const与non-const的变量和成员函数,最重要的是下表:
由上表可知,当成员函数的const和non-const版本同时存在时,const object只能调用const版本,non-const object只能调用non-const版本。
5、重载new(),delete()
5.1 课堂内容总结
5.2课后补充学习
(1)局部重载new和delete
局部重载new和delete,可以使用成员函数和友元函数两种方式重载。使用new分配某个重载了new的累的对象空间时,先调用new的重载函数,再调用该类的构造函数,如果该类的构造函数有参数要求,则必须给出对应的实参。使用了delete释放某个重载了delete的累的对象空间时,先调用类的析构函数,然后再调用重载的delete函数。
(2)全局重载new和delete
可以在任何类说明之外重在new和delete,使它们成为全局的。当new和delete被重载为全局时,C++原来的new与delete被忽略,并且重载的运算符用于所有类型(包括标准型和用户定义类型)的分配要求。