1.3继承与类作用域
来源:互联网 发布:怎么进入人工智能行业 编辑:程序博客网 时间:2024/06/02 17:45
1.3继承与类作用域
每个类都拥有自己的作用域,在这个作用域内,我们定义类的成员。
当存在继承关系时,派生类的作用域嵌套在其基类的作用域之内。
如果一个名字在派生类的作用域内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义。
函数调用的解析过程
假设我们调用p->mem()或obj.mem():
- 确定p(或obj)的静态类型。
- 在p(或obj)的静态类型对应的类中查找mem。如果没找到,则依次在直接基类中不断查找mem,直到到达继承链的顶端。
- 一旦找到了mem,就进行常规的类型检查以确认对于当前找到的mem,本次调用是否合法。
- 假设调用合法,则编译器将根据调用的是否是虚函数而产生不同的代码:
- 如果mem是虚函数,并且我们是通过引用或指针进行的调用,则编译器产生的代码将在运行时确定到底运行该虚函数的哪个版本,依据是对象的动态类型。
- 反之,如果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}
阅读全文
0 0
- 1.3继承与类作用域
- 继承与派生:作用域分辨符
- 继承中的类作用域
- 继承中的类作用域
- 抽象基类、访问控制与继承和继承中的类作用域
- 继承情况下的类作用域
- C++ 继承中类作用域
- 多重继承下的类作用域
- 继承中的类作用域(1)
- 继承中的类作用域(2)
- 继承情况下类的作用域
- 四十一、继承与派生:作用域分辨符
- javascript作用域与作用域链、闭包、对象创建模式、继承模式
- 【C++继承】之虚拟继承、作用域
- 继承-虚函数-作用域
- Angulars Controller作用域继承
- 作用域层级和继承
- C++中继承情况下的类作用域
- Java集合概念及List和Map遍历
- 关于webfrom的页面绑定后台获取
- 关于基类指针指向子类对象,构造函数和析构函数调用的顺序的问题。
- Microsoft Visual Studio 中printf的替代函数OutputDebugString
- C++和Lua交互教程(基于LuaBridge)
- 1.3继承与类作用域
- 二分搜索应用二
- [NOTE][gitHub]Fetching latest commit…
- 跟我学习dubbo-简介(1)
- 正则校验只能输入整数或小数
- B-tree 和B+tree
- Inno Setup入门(十)——操作注册表
- payload 2
- YOLO: Real-Time Object Detection深度网络: 在Darknet上的实现方式