C++-----深度探索对象模型-第一章-关于对象(二)

1、C++兼容C的struct关键字。

2、C中struct更偏于数据封装,C++则不仅仅是封装性还包括了继承性。struct的本身带有public,class本身带有private。

3、在C++中凡是处于同一个access section的数据必定保证其声明顺序在内存的顺序一致,但是不同的access section中就不一定了。

4、在C++中使用struct的建议是:将数据封装起来,没有继承的情况下,传递给C++使用。

5、C struct在C++中一个合理用途是当以传递一个复杂的class objects的全部或部分到某个C函数时,struct声明可以将数据封装起来。并保证拥有与C兼容的空间布局。

6、C++程序设计模型支持三种程序范式:

    *程序模型:和C一样,C++也支持。

    *抽象数据类型模型:有类的概念,但是没有多态的概念。

    *面向对象OO:有类以及多态特性的出现。

7、只有通过指针或引用的间接处理,才支持OO程序设计所需的多态性质。

8、多态的定义:把具有继承关系的多个类型成为多态。

9、虚函数与非虚函数与多态的关系:虚函数运行时才会决定执行的是哪个版本,判断的依据是引用或指针所绑定的真实类型。非虚函数的调用在编译时期已经确定。

10、public继承中,可以直接进行多态的转换,一个父类类型指针可以指向这个类的对象,也可以指向根据public继承的一个子类型。nonpublic继承和类型为void*指针可以说是多态的,但是必须通过程序员显示转换操作管理。

11、C++以下列方式支持多态:

    1)经由一组隐式的转化操作,例如把一个派生类指针drived class转化为一个指向其公有继承的基类指针。

    2)虚函数机制。

    3)经由dynamic_cast和typeid运算符。

12、多态的用途是经过一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中。共享接口是通过虚函数机制引发的。他可以根据执行期根据对象的真正类型解析出来到底是哪一个函数实例被调用。

13、class 对象内存大小:

    1)其nonstatic data member的大小总和。

    2)加上任何由于alignment的需求而填补上去的空间,可能存在与member之间也可能存在与集合体边界。

    3)加上为了支持虚函数而产生的额外负担,其实就是虚函数指针。

14、指针本身的大小内存是确定的,无论指向哪种类型。同理引用本质上也是指针,其本身所需的内存也是固定的。但是,两者不同的是sizeof一个指针返回的是指针本身大小,而sizeof一个引用返回的是引用的对象的大小。

15、指针的不同是它所寻址出来的对象类型不同。也就是说指针类型会教导编译器如何解释某个特定地址中内存内容及其大小。

16、而一个void*类型的指针,是无法知道它涵盖的地址空间的,它只能持有一个地址,无法利用它操作其指向对象。

17、cast,转换,其实是一种编译器指令,大部分情况下它并不改变一个指针所含的真正地址,只影响被指出的内存的大小和内容。

18、当给一个基类指针绑定一个其派生类的对象时,这个指针所涵盖的范围只有其基类中含有的部分,不包括派生类中的成员,而派生类指针是包含整个派生类对象的。

19、下面有两个类,有如下声明。

//以下代码省略一些部分,只是为了说明问题
class ZooAnimal{
public:
    ZooAnimal();
    virtual ~ZooAnimal();
    //...
    virtual void rotate();
protected:
    int loc;
    string name;
};

class Bear:public ZooAnimal{
public:
    Bear();
    ~Bear();
    //...
    void rotate();
    virtual void dance();
protected:
    enum{..};
    Dance dance_know;
    int cell_block;
};

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

pz和pb两个指针,都指向b的第一个byte,差别是,pb所涵盖的地址包含整个Bear对象,而pz只包含Bear对象中的ZooAnimal对象。

除了基类ZooAnimal中的成员,不能使用pz来处理Bear的任何成员唯一例外是通过虚函数机制。

//下面不合法,cell_block不是基类的成员,虽然此时pz指向派生类。
pz->cell_block;

//经过一个显式转换是可以的,如下
(static_cast<Bear*>(pz))->cell_block;

//下面这个更好
if(Bear* pb2=dynamic_cast<Bear*> (pz))
pb2->cell_bloclk;

//没问题,因为pb本身就是Bear*类型指针。
pb->cell_block;

20、当写如下语句时,

pz->rotate();

pz的类型会在编译时期决定以下两点:

    1)固定可用的接口,也就是说pz只能调用ZooAnimal的public接口。

    2)该接口的access levbel,访问级别。

在每一个执行点,pz所指向的对象类型可以决定rotate()所调用的实例。类型信息的封装并不是维护在pz中,而是维护在link中,link存在于类对象的虚函数指针和虚函数表之间。

21、一个指针或引用之所以支持多态,是因为它们并不引发内存中任何有关内存委托操作,会受到改变的只有它们所指的内存的大小和解释方式。

22、当一个基类对象直接初始化为一个派生类对象时,派生类对象会被切割以塞入较小的基类类型的内存中。

23、C++也支持ADT程序风格,如果称为Object-based(OB),例如String class,一种非多态数据类型。它提供一个public接口和一个private实现品,包括数据和算法,但是不支持类型的扩充。一个OB设计可能比一个对等的OO设计速度更快而且空间更紧凑。速度快是因为所有函数调用操作在编译时期解析完成,对象建构起来不需要设置virtual机制。空间紧凑是因为每一个class object不需要负担传统意义上为了支持virtual机制而需要的额外负担。

24、cast的类型:dynamic_cast 安全的向下转移(指的是基类的指针或引用转换到派生类的指针或引用),const_cast 去除常量性,static_cast 强制转换类型,reinterpret_cast 底层转换。

posted @ 2019-05-15 10:22  吾之求索  阅读(110)  评论(0)    收藏  举报