chapter 1

C++ 在布局以及存取时间上的额外开销是由virtual引起:

A. virtual function 机制

B. virtual base class 

1.1 C++对象模型

知识点 1

class Point {
public:
    Point(float xval);
    virtual ~Point();
    
    float x() const;
    static int PointCount();
protected:
    virtual ostream& 
        print (ostream&os) const;
    float _x;
    static int _point_count;
}; 

该函数声明包含:

3种 class member functions: static、nonstatic 和 virtual
2种 class data members: static 和 nonstatic

C++对象模型
clipboard.png

1. C++中的虚函数是通过虚函数表(vtbl)来实现.
2. 每一个类对象会被安插一个指针(vptr),指向该类的虚函数表。
3. vptr的设定和重置都由每一个类的构造函数、析构函数和复制赋值运算符自动完成。

知识点 2 C++支持多重继承

class iostream:
    public istream,
    public ostream {}; 
    
class istream : virtual public ios{};
class ostream : virtual public ios{};

暂略

知识点 3 策略性正确的struct

C++中凡处于同一个access section(public, protected, private)的数据,必定保证以其声明顺序出现在内存布局中。
然而被放置在多个access sections 中的各数据,排列顺序就不一定了

C struct 在C++中的一个合理用途,是当你要传递“一个复杂的class object 的全部或部分”到某个C函数去时,
struct声明可以将数据封装起来,并保证拥有与C兼容的空间布局。然而这项保证只在组合的情况下才存在
``

知识点 4

需要多少内存才能表现一个class object
1. nonstatic data members 的总和
2. 因alignment的需求而填补(padding)上去的空间
3. 因支持virtual而由内部产生的任何额外负担

知识点 5 指针的类型

ZooAnimal *px;
int *ptr;
vector<String>* ptr;

三个指针的不同之处在于其寻址出来的object类型不同。
也就说“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小
转换是一种编译器指令。一般不改变一个指针所含的真正地址,它只影响 “被指出之内存的大小和其内容的解释方式”

加上多态之后:

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 Dances { ... };
    Dances dances-known;
    int cell_block;
};

内存布局
clipboard.png

Bear b;
ZooAnimal za = b; 

za.rotate();

为什么rotate()所调用的是ZooAnimal实例而不是Bear ?

编译器确保如果某个object含有一个及以上的vptrs,那些vptrs的内容不会被base class object 初始化或改变

P34 : 如果virtual funtion 被定义为inline,则更有效率上的收获 ??
virtual function 是在运行期间确定的,inline function 在编译期被确定, 两者不是冲突吗

本文固定链接: http://www.js-code.com/cpp/cpp_58528.html