玩命加载中 . . .

15.5-继承中的类作用域


15.5 继承中的类作用域

如果一个名字在派生类的作用域无法解析,则编译器将继续在外层的基类作用域中寻找该名字的定义

继承关系
Bulk_quote -> Disc_quote -> Quote
Bulk_quote bulk;
cout << bulk.isbn();

Bulk_quote中查找isbn函数失败,没定义,所以往上找,Disc_quote中也没有,再往上,在Quote中找到了

静态类型决定了哪些成员是可见的

Disc_quote中定义了一个函数discount_policy

class Disc_quote {
    pair<size_t, double> discount_policy() const {
        return {quantity, discount};
    }
};

Bulk_quote bulk;
Bulk_quote *bulkP = &bulk;  // 静态类型与动态类型一致
Quote *itemP = &bulk;       // 静态类型与动态类型不一致
bulkP->discount_policy();   // 正确
itemP->discount_policy();   // 错误

bulkP的静态类型是Bulk_quote,调用discount_policy时,先在Bulk_quote中找,没找到,就往上,在Disc_quote中找到,调用成功

itemP的静态类型是Quote,调用discount_policy时,在Quote中找没找到,往上已经没有了,所以调用失败

派生类的成员将隐藏同名的基类成员

struct Base {
    Base(): mem(0) {}   // Base::mem进行默认初始化
protected:
    int mem;
};

struct Derived: Base {
    Derive(int i): mem(i) {}    // 用i初始化Derived::mem
    int get_mem() { return mem; }
protected:
    int mem;    // 隐藏基类中的mem
};
struct Base {
    int memfcn();
};

struct Derived: Base {
    int memfcn(int);    // 隐藏了基类的memfcn
};

Base b;
Derived d;
b.memfcn();     // 调用Base::memfcn
d.memfcn(10);   // 调用Derived::memfcn
d.memfcn();     // 错误,基类的memfcn被隐藏了无法调用
d.Base::memfcn();   // 显式地说明要调用基类的memfcn

虚函数与作用域

struct Base {
public:
    virtual int fcn();
};

class D1: public Base {
public:
    // 继承了Base::fcn的定义,没有override
    int fcn(int);   // 隐藏了基类的fcn,不是虚函数
    virtual void f2();  // 声明了一个虚函数
};

struct D2: public D1 {
    int fcn(int);   // 不是虚函数,隐藏了D1::fcn(int)
    int fcn();  // override Base::fcn()
    void f2();  // override D1::f2()
};

Base bobj; 
D1 d1obj; 
D2 d2obj;
Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
bp1->fcn(); // 调用Base::fcn()
bp2->fcn(); // 调用Base::fcn()
bp3->fcn(); // 调用D2::fcn()

bp2的静态类型是Base,动态类型是D1,调用fcn时,因为D1没有覆盖Basefcn,所以还是调用Basefcn

bp3的静态类型是Base,动态类型是D2, 调用fcn时,因为D2有覆盖Basefcn,所以调用D2版本的fcn

D1 *d1p = &d1obj;
D2 *d2p = &d2obj;
bp2->f2();  // 错误,Base中没有f2,调用失败,静态类型决定接口
d1p->f2();  // 正确,调用D1::f2()
d2p->d2();  // 正确,调用D2::f2()

bp2的静态类型是Base,调用f2时,在Base中没找到f2,所以调用失败
d1p的静态类型和动态类型是D1,调用f2时,在D1中找到了f2,所以调用D1::f2
d2p的静态类型和动态类型是D2,调用f2时,在D2中找到了f2,所以调用D2::f2

Base *p1 = &d2obj;  // 静态类型Base,动态类型D2
D1 *p2 = &d2obj;    // 静态类型D1,动态类型D2
D2 *p3 = &d2obj;    // 静态类型D2,动态类型D2
p1->fcn(42);    // 错误,静态类型Base中没有fcn(int)
p2->fcn(42);    // 静态绑定,非虚函数,调用D1::fcn(int)
p3->fcn(42);    // 静态绑定,非虚函数,调用D2::fcn(int)

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录