所有有 virtual 的类的对象里面最头上就会自动加上一个隐藏的不让你知道的指针, 那个指针叫做 vptr(virtual pointer)
它指向一张表,那张表叫做 vtable, 里面是所有virtual函数的地址
这个 vtable 不是对象的,而是这个类的

如果一个类的函数只要有一个是virtual的,那么它的析构函数也必须是virtual的
所有的oop语言默认都是virtual的,只有C++默认是静态绑定的,所有它才可以说是做成动态绑定的,
c++这样做是因为效率

override 覆盖
void Derived::func()
{
    cout << "In Derived func" << endl;
    Base::func();           // 在子类的func函数中调用父类的func函数
}

如果在父类中有两个函数重载为虚函数,那么在子类中也必须让这两个函数重载为虚函数,如果子类中只有一个,那么另一个就会被隐藏
发生 namehidding, oop语言中只有C++ 会发生namehidding


如果一个类的成员变量是 referencec(引用) 那么意味着当你去声明它的时候,你没有办法给他一个初始值
然后必须在这个类的构造函数得到初始化列表中给他写出来
一个函数返回一个reference是可以的,和指针一样,不能返回这个函数的本地变量的reference
当要返回一个引用时,写在return哪里的时一个变量,没有其他符号

将一个对象传递进函数,一般用常引用的方法,如果直接传递一个对象进去会发生大量的数据传递,而不是只是一个指针或者变量
引用传参必须给出一个明确的有地址的对象,不能是 f(i * 3) 这样类型的
但是如果是常引用则没问题

learning record code:

#include <iostream>
#include <assert.h>
using namespace std;
const int SIZE = 32;

double myarray[SIZE];
double &subscript(int x)
{
    return myarray[12];
}

class A{
    public:
        int i;
        A() : i(10) {}
        // virtual void f2() {cout << "" << endl;}
        // virtual void f() { cout << "A::f() i = " << i << endl; }
};

class B : public A{
    public:
        B() : j(20) {}
        virtual void f(){ cout << "B::f()" << j << endl; } 
        int j;
};

// void f(const int &num)
// {
//     cout << num << endl;
// }

A f()
{
    A a;
    return a;
}

int main()
{
    A b;
    b.i = 20;
    f() = b;

    for(int i=0; i<SIZE; i++)
    {
        myarray[i] = i * 1.5;
    }
    // 表面上看时类型不匹配的, 右边的时一个引用, 左边时一个变量
    // 实际上发生的是,将右边的值赋值给左边的变量,发生了非引用
    double val = subscript(12);
    subscript(3) = 34.5;    // 返回的是一个引用,所以可以作为一个变量来使用


    // A a;
    // B b;

    // A *p = &a;
    // int *r = (int *) &a;
    // int *t = (int *) &b;
    // *r = *t;

    // p->f();
    // cout << sizeof(a) << endl;

    // int *p = (int *) &a;        // p 和 q 是不一样的,但是*p和*q 是一样的
    // int *q = (int *) &b;
    // cout << *p << endl;
    // cout << *q << endl;

    // int *x = (int *) *p;
    // cout << x << endl;

    return 0;
}