1. Avoid hiding inherited names避免掩盖继承而来的名字

  2. Never redefine an inherited non-virtual function绝不重新定义继承而来的非虚函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class A {
public:
// virtual
void func() { std::cout << "A::func()\n"; }
};

class B : public A {
public:
void func() { std::cout << "B::func()\n"; }
};

class C : public A {
public:
void func() { std::cout << "C::func()\n"; }
};

int main() {
C *pc = new C(); //pc的静态类型是它声明的类型C*,动态类型也是C*;
B *pb = new B(); //pb的静态类型和动态类型也都是B*;
A *pa = pc; //pa的静态类型是它声明的类型A*,动态类型是pa所指向的对象pc的类型C*;
pa = pb; //pa的动态类型可以更改,现在它的动态类型是B*,但其静态类型仍是声明时候的A*;
C *pnull = nullptr; //pnull的静态类型是它声明的类型C*,没有动态类型,因为它指向了NULL;
pa->func(); //A::func() pa的静态类型永远都是A*,不管其指向的是哪个子类,都是直接调用A::func();
pc->func(); //C::func() pc的动、静态类型都是C*,因此调用C::func();
pnull->func(); //C::func() 不用奇怪为什么空指针也可以调用函数,因为这在编译期就确定了,和指针空不空没关系;
}
  1. Never redefine a function's inherited default parameter value绝不重新定义继承而来的缺省参数值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class E{
    public:
    virtual void func(int i = 0)
    {
    std::cout << "E::func()\t"<< i <<"\n";
    }
    };
    class F : public E
    {
    public:
    virtual void func(int i = 1)
    {
    std::cout << "F::func()\t" << i <<"\n";
    }
    };

    void test2()
    {
    F* pf = new F();
    E* pe = pf;
    pf->func(); //F::func() 1 正常,就该如此;
    pe->func(); //F::func() 0 哇哦,这是什么情况,调用了子类的函数,却使用了基类中参数的默认值!
    }
    image.png