《深度探索C++对象模型》第1章重点:关于对象

c++对象模型的设计:nonstaticdata members被放置于每一个class之内,staticdata members则被放置于class之外,staticnonstaticfunction被放置于class之外。virtual function以下面两个步骤支持:

  1. 每个class产生一个virtual tablevtbl),里面存放指向每个virtual function的指针。
  2. 每一个class对象有一个指针vptr,指向相关的vtblvptr的设定和重置由每个class的构造函数、析构函数和copy assignment运算符自动完成。vtbl的第一个slot通常放的是这个classtype_info object指针,用以支持runtime type identificationRTTI

static变量存放于全局变量区(.data),是为符合static语义,其需要在类外进行初始化,分配内存,因为它的生命周期是全局,而class对象的生命周期在它被定义之后才开始。

 

c++classstruct的差异:struct可以干class的所有事情,只是struct的默认成员访问权限为publicclass的默认成员访问权限为privatestruct默认是公有继承,class默认是私有继承;当structclass中没有构造函数且成员变量(无需成员函数)全为public时,可以用{}进行初始化。

struct适合看成是一个数据的集合体;class适合看成一个对象。

c++以下列方法支持多态:

  1. 经由一组隐式的转化操作,例如将派生类指针转化为一个指向其基类的指针:

    Shape *ps = new Circle();

  2. 经由virtual function机制:

    ps -> rotate();

  3.经由dynamic_casttypeid运算符

    if(Circle *pc = dynamic_cast<Circle*>(ps)) ...

typeid本质上即是通过虚函数表的第一个slot内的指针所指向的type_info object来判断是哪种class 

多态的主要用途是经由一个共同的接口来影响类型的封装,这个接口通常定义在基类中,并在不同的派生类中有不同的实现。通过virtual function机制在运行时才确定到底调用哪个函数实例。

void rotate(X datum, const X *pointer, const X& reference) {
    //下面这个操作总是调用X::rotate(),因为datum的类型已经确定,不走虚函数表的方式;
    datum.rotate();
    //下面这两个操作必须在运行期才能知道调用的是那个rotate()实例
    (*pointer).rotate();
    reference.rotate();
}
main() {
    Z z; //Z是X的一个子类型
    rotate(z, &z, z);
    return 0;
}

不同类型指针的差别:只在其所寻址出来的object类型不同,“指针类型”会教导编译器如何解释某个特定地址的内存内容及大小。一个类型为void*的指针只能够持有一个地址,而不能通过它操作所指的object

Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

pzpb都指向Bear object的第一个byte,其间差别:pb所涵盖的地址包含整个Bear object,而pz所涵盖的地址只包含Bear object中的zooAnimal部分。

Bear b;
ZooAnimal za = b; //引起切割,事实上会调用拷贝构造函数,设定正确的vptr
za.rotate(); //调用ZooAnimal::rotate(),在编译器就已经确定

一个指针或者引用之所以支持多态,是因为它们不引发内存中与类型相关的改变,而只改变它们所指向内存的“大小和内容解释方式”。

 

猜你喜欢

转载自www.cnblogs.com/senshaw/p/10944439.html