类其实也是一种作用域,每个类都会定义它自己的作用域,在这个作用域内我们再定义类的成员。当存在继承关系时,派生类的作用域嵌套在基类的作用域之内,如果一个名字在派生类的作用域内无法找到,编译器会继续到外层的基类作用域中查找该名字的定义。
换句话说,作用域能够彼此包含,被包含(或者说被嵌套)的作用域称为内层作用域(inner scope),包含着别的作用域的作用域称为外层作用域(outer scope)。一旦在外层作用域中声明(或者定义)了某个名字,那么它所嵌套着的所有内层作用域中都能访问这个名字。同时,允许在内层作用域中重新定义外层作用域中已有的名字。
假设 Base 是基类,Derived 是派生类,那么它们的作用域的嵌套关系如下图所示
派生类的作用域位于基类作用域之内这一事实可能有点出人意料,毕竟在我们的代码中派生类和基类的定义是相互分离的。不过也恰恰因为类作用域有这种继承嵌套的关系,所以派生类才能像使用自己的成员一样来使用基类的成员。
#include using namespace std; class A{ public: void func(); public: int n; }; void A::func(){ cout<<"www.zzaxw.com"<<endl; } class B: public A{ public: int n; int m; }; class C: public B{ public: int n; int x; }; int main(){ C obj; obj.n; obj.func(); cout<<sizeof(C)<<endl; return 0; }
运行结果:
www.zzaxw.com
20
本例中,B 继承自 A,C继承自 B,它们作用域的嵌套关系如下图所示:
obj 是 C 类的对象,通过 obj 访问成员变量 n 时,在 C 类的作用域中就能够找到了 n 这个名字。虽然 A 类和 B 类都有名字 n,但编译器不会到它们的作用域中查找,所以是不可见的,也即派生类中的 n 遮蔽了基类中的 n。
通过 obj 访问成员函数 func() 时,在 C 类的作用域中没有找到 func 这个名字,编译器继续到 B 类的作用域(外层作用域)中查找,仍然没有找到,再继续到 A 类的作用域中查找,结果就发现了 func 这个名字,于是查找结束,编译器决定调用 A 类作用域中的 func() 函数。
这个过程叫做名字查找(name lookup),也就是在作用域链中寻找与所用名字最匹配的声明(或定义)的过程。
联系信息:邮箱aoxolcom@163.com或见网站底部。
请登录后发表评论
注册
社交帐号登录