zoukankan      html  css  js  c++  java
  • 继承中类的作用域

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

    名字冲突与继承

    派生类中能重定义在其直接基类或间接基类中的名字,此时定义在内层作用域(即派生类)的名字将隐藏定义在外层作用域(即基类)的名字。

    struct Base{
    	Base():mem(0){}
    protected int mem;
    };
    
    struct Derived : Base{
    	Derived(int i):mem(i){}
    	int get_mem() {return mem;}
    protected int mem;		//@ 隐藏基类中的mem
    };
    

    通过作用域符来使用隐藏的成员

    可以通过作用域符来访问被隐藏的基类成员:

    struct Derived : Base{
    	int get_base_mem(){return Base::mem;}
    	//...
    };
    

    作用运算符将覆盖掉原有的查找规则,并指示编译器从 Base 类的作用域开始查找 mem

    注意:

    除了覆盖继承而来的虚函数之外,派生类最好不要重用其他定义在基类中的名字。

    一如往常,名字查找先于类型检查

    如果派生类的成员与基类的某个成员同名,则派生类将在其作用域内隐藏该基类成员,即使派生类成员与基类成员的形参列表不一致,基类成员也会被隐藏。

    struct Base{
    	int memfunc();
    };
    
    struct Derived : Base{
    	int memfunc(int);
    };
    
    Derived d;Base b;
    b.memfunc();		//@ 正确
    d.memfunc(10);		//@ 正确
    d.memfunc();		//@ 错误,参数列表为空的基类成员函数被隐藏
    d.Base::memfunc();		//@ 正确
    

    虚函数与作用域

    基类和派生类的虚函数接受的实参必须相同,否则就无法通过基类的引用或者指针调用派生类的虚函数。

    class Base{
    public:
    	virtual int fun();
    };
    
    class D1 : public Base{
    public:
    	int fun(int);		//@ 隐藏了Base中的fun函数
    	virtual void f2();
    };
    
    class D2 : public D1{
    public:
    	int fun(int);		//@ 隐藏了D1 中的 fun 函数
    	int fun();			//@ 覆盖了Base 中的 fun 函数
    	void f2();			//@ 覆盖了 D1 中的 f2 函数
    };
    

    通过基类调用隐藏的虚函数

    Base bobj;D1 d1obj;D2 d2obj;
    Base* bp1 = &bobj,*bp2 = &d1obj,*bp3 = &d2obj;
    
    bp1->fun();		//@ 调用Base::fun
    bp2->fun();		//@ 调用Base::fun
    bp3->fun();		//@ 调用D2::fun
    
    D1 *d1p = &d1obj;D2 *d2p = &d2obj;
    bp2->f2();		//@ 错误,Base没有名字为f2的成员
    d1p->f2();		//@ 调用D1::f2
    d2p->f2();		//@ 调用D2::f2
    
    Base *p1 = &d2obj;D1 *p2 = &d2onj;D2 *p3 = &2dobj;
    p1->fun(42);		//@ 错误,Base中没有接受一个int的fun
    p2->fun(42);		//@ 静态绑定,调用D1::fun(int)
    p3->fun(42);		//@ 静态绑定,调用D2::fun(int)
    

    覆盖重载的函数

    成员函数无论是否是虚函数,都可以被重载,派生类可以覆盖重载函数的0个或多个实例,如果派生类希望所有的重载版本对它来说都是可见的,那么它就需要覆盖所有的版本,或者一个也不覆盖。

    有时候只需要覆盖重载集合中的一个版本,而不得不覆盖基类中的每一个版本,显然很麻烦。一种的好的解决办法是为重载成员提供一条 using 声明语句,这样就不需要覆盖基类中的每一个重载版本。using 声明语句指定了一个名字而不指定形参列表,所以一条基类成员函数的 using 声明语句就能把该函数的所有重载实例添加到派生类的作用域中,此时派生类只需要定义其特有的版本即可,无需为继承而来的。

  • 相关阅读:
    Eclipse常用插件推荐
    Open Source Search Engines in Java
    Java: convert a file to a byte array, then convert byte array to a file.
    常用的Eclipse插件介绍
    一个搜索引擎周边的blog
    java文件读取。(单字节读取和按行读取读取)
    im4java
    csv格式读取通用类
    java以流方式下载文件struts2.x版_心灵的港湾_百度空间
    Jetty/Feature/Jetty Maven Plugin
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12496349.html
Copyright © 2011-2022 走看看