C++类继承时的作用域嵌套,破解C++继承的一切秘密!

类其实也是一种作用域,每个类都会定义它自己的作用域,在这个作用域内我们再定义类的成员。当存在继承关系时,派生类的作用域嵌套在基类的作用域之内,如果一个名字在派生类的作用域内无法找到,编译器会继续到外层的基类作用域中查找该名字的定义。

换句话说,作用域能够彼此包含,被包含(或者说被嵌套)的作用域称为内层作用域(inner scope),包含着别的作用域的作用域称为外层作用域(outer scope)。一旦在外层作用域中声明(或者定义)了某个名字,那么它所嵌套着的所有内层作用域中都能访问这个名字。同时,允许在内层作用域中重新定义外层作用域中已有的名字。

假设 Base 是基类,Derived 是派生类,那么它们的作用域的嵌套关系如下图所示

C++类继承时的作用域嵌套,破解C++继承的一切秘密!
派生类的作用域位于基类作用域之内这一事实可能有点出人意料,毕竟在我们的代码中派生类和基类的定义是相互分离的。不过也恰恰因为类作用域有这种继承嵌套的关系,所以派生类才能像使用自己的成员一样来使用基类的成员。

#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,它们作用域的嵌套关系如下图所示:

C++类继承时的作用域嵌套,破解C++继承的一切秘密!
obj 是 C 类的对象,通过 obj 访问成员变量 n 时,在 C 类的作用域中就能够找到了 n 这个名字。虽然 A 类和 B 类都有名字 n,但编译器不会到它们的作用域中查找,所以是不可见的,也即派生类中的 n 遮蔽了基类中的 n。

通过 obj 访问成员函数 func() 时,在 C 类的作用域中没有找到 func 这个名字,编译器继续到 B 类的作用域(外层作用域)中查找,仍然没有找到,再继续到 A 类的作用域中查找,结果就发现了 func 这个名字,于是查找结束,编译器决定调用 A 类作用域中的 func() 函数。

这个过程叫做名字查找(name lookup),也就是在作用域链中寻找与所用名字最匹配的声明(或定义)的过程。

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论