何时使用protected

使用protected使得子类可以直接访问父类成员,意味着如果你对protected成员作修改,你可能要修改父类和所有子类

使用private意味着对实现细节的封装

一般只需要使用public inherit

在子类redefine函数时,access modifier只取决于子类中这个函数的modifier,与父类中的无关

Overload resolution

class Base
{
public:
    void print(int)    { std::cout << "Base::print(int)\n"; }
    void print(double) { std::cout << "Base::print(double)\n"; }
};
 
class Derived: public Base
{
public:
    void print(double) { std::cout << "Derived::print(double)"; } // this function added
};

derived.print(1)会匹配到derive中的print,为了改变这一行为,推荐在derive中使用using引入base的print(int)

using还会根据他自己在哪个access modifier修饰下,改变引入函数的modifier,并且不难认为using会将所有该函数的重载的modifier都修改

Access controls are not enforced at runtime.

class A{
public: virtual void fun()
};
 
class B : public A{
private: virtual void fun()
};
 
int main()
{
    B b {};
    b.fun();                  // compile error: not allowed as B::fun() is private
    static_cast<A&>(b).fun(); // okay: A::fun() is public, resolves to private B::fun() at runtime
}

mixin

mixin是用来被继承,在继承它的类中增加一些属性的。mixin的名字表达了他不应该instantiated on its own

mixin通常不使用虚函数而使用模版

Curiously Recurring Template Pattern

一个类继承一个模版类,使用他自己作为模版参数

template<class Z>
class Y {};
class X : public Y<X> {};

Diamond Problem

菱形继承

虚函数

使得函数总是解析到最derived版本

使得基类指针和引用调用派生类函数

If a function is virtual, all matching overrides in derived classes are implicitly virtual.

because the override specifier implies virtual, there’s no need to tag functions using the override specifier with the virtual keyword

在基类中使用virtual,在子类中使用override即可

编译期多态

函数重载解析和模版解析

early binding/static binding

编译期解析

运行期多态

late binding/dynamic dispatch

函数指针

虚函数解析

covariant return types

允许虚函数的返回指针/引用类型不同,是所override函数的子类

vptr是最base的类的成员,是一个指向虚函数表的指针,它实际占用类的内存(和this不同)。

纯虚函数也可以有定义,这仍然会对子类的定义有要求。这个定义可以被子类使用

析构函数可以是纯虚的,但必须有定义

virtual base class

使得菱形继承时共用基类且基类只被构造一次

virtual base class会先于所有non virtual的构造

Frankenobject

int main()
{
    Derived d1{ 5 };
    Derived d2{ 6 };
    Base& b{ d2 };
    b = d1; // this line is problematic
    return 0;
}

由于拷贝构造函数不是虚函数,只复制了d1的base部分

linux堆空间分配系统调用brk和mmap

运行库管理堆空间分配,避免频繁系统调用

malloc对小对象会在现有空间中直接寻找可分配的块,对大对象直接使用mmap

Which book is best for system programming (APUE vs TLPI)? : r/kernel (reddit.com)