1.3继承与类作用域

来源:互联网 发布:怎么进入人工智能行业 编辑:程序博客网 时间:2024/06/02 17:45

1.3继承与类作用域

每个类都拥有自己的作用域,在这个作用域内,我们定义类的成员。

当存在继承关系时,派生类的作用域嵌套在其基类的作用域之内。

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

这里写图片描述

函数调用的解析过程

假设我们调用p->mem()或obj.mem():

  1. 确定p(或obj)的静态类型。
  2. 在p(或obj)的静态类型对应的类中查找mem。如果没找到,则依次在直接基类中不断查找mem,直到到达继承链的顶端。
  3. 一旦找到了mem,就进行常规的类型检查以确认对于当前找到的mem,本次调用是否合法。
  4. 假设调用合法,则编译器将根据调用的是否是虚函数而产生不同的代码:
    1. 如果mem是虚函数,并且我们是通过引用或指针进行的调用,则编译器产生的代码将在运行时确定到底运行该虚函数的哪个版本,依据是对象的动态类型。
    2. 反之,如果mem不是虚函数,或者我们是通过对象(而非引用或指针)进行的调用,则编译器将产生一个常规函数调用。

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

定义在内层作用域(派生类)的名字将隐藏定义在外层作用域(基类)的名字。

和其他作用域一样,派生类也能重新使用定义在其直接基类或间接基类中的名字。但是,除了覆盖继承而来的虚函数之外,派生类最好不要重新使用其他定义在基类中的名字。

#include <iostream>using namespace std;class Base{public:    Base(): mem(0){}protected:    int mem;};class Derived: public Base{public:    Derived(int i): mem(i){}    int get_mem()    {        return mem;    }protected:    int mem;};int main(){    Derived d(42);    cout << d.get_mem() << endl; // 42}

但是,我们可以通过作用域运算符来使用一个被隐藏的基类成员。作用域运算符将覆盖原有的查找规则,并指示编译器从特定类的作用域开始查找。

#include <iostream>using namespace std;class Base{public:    Base(): mem(0){}protected:    int mem;};class Derived: public Base{public:    Derived(int i): mem(i){}    int get_mem()    {        return Base::mem;    }protected:    int mem;};int main(){    Derived d(42);    cout << d.get_mem() << endl; // 0}

派生类成员函数不会重载(而是隐藏)基类同名成员函数

声明在内层作用域的函数并不会重载声明在外层作用域的函数。因此,定义在派生类中的成员函数也不会重载其基类中的成员函数。

和其他作用域一样,如果派生类(内层作用域)的成员函数和基类(外层作用域)的某个成员函数同名,则派生类将在其作用域内隐藏该基类成员函数。即使派生类成员函数和基类成员函数的形参列表不一致,基类成员函数也仍会被隐藏掉。

#include <iostream>using namespace std;class Base{private:    int x;public:    virtual void mf1(){cout << "Base::mf1()" << endl;}    virtual void mf1(int n) {cout << "Base::mf1(int n)" << endl;}    virtual void mf2(){cout << "Base::mf2()" << endl;}    void mf3(){cout << "Base::mf3()" << endl;}    void mf3(double d){cout << "Base::mf3(double d)" << endl;}};class Derived: public Base{public:    virtual void mf1(){cout << "Derived::mf1()" << endl;}    void mf3(){cout << "Derived::mf3()" << endl;}    void mf4(){cout << "Derived::mf4()" << endl;}};int main(){    int x;    Base base;    Derived derived;    derived.mf1(); //Derived::mf1()    derived.mf1(x); //error    derived.mf2(); //Base::mf2()    derived.mf3(); //Derived::mf3()    derived.mf3(x); //error}

这里写图片描述

#include <iostream>using namespace std;class Base{public:    int memfcn()    {        cout << "Base::memfcn" << endl;    }};class Derived: public Base{public:    int memfcn(int i)    {        cout << "Derived::memfcn" << endl;    }};int main(){    Base b;    Derived d;    b.memfcn(); //Base::memfcn    d.memfcn(10); //Derived::memfcn    d.memfcn(); //error    d.Base::memfcn(); //Base::memfcn}

原创粉丝点击