zoukankan      html  css  js  c++  java
  • 关于C++中继承、重载、掩盖 《转载》

    关于C++中继承、重载、掩盖

    MoaKap

    在开始之前,我们可以先看下面这个小程序:

    #include <iostream>

    using namespace std;

     

    class Base

    {

    private:

           int x;

    public:

           virtual void mf1()

           {

                  cout<<"Base: mf1()"<<endl;

           }

           virtual void mf1(int)

           {

                  cout<<"Base: mf1(int)"<<endl;

           }

           virtual void mf2()

           {

                  cout<<"Base: mf2()"<<endl;

           }

           void mf3(double)

           {

                  cout<<"Base: mf3(double)"<<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()

    {

           Derived d;

           int x = 100;

           d.mf1();

           d.mf1(x);

           d.mf2();

           d.mf3();

           d.mf3(x);

           d.mf4();

    }

     

    如果你能很清楚地搞清楚各个函数的调用过程,那以下的内容你就不要再浪费时间了。否则,就耐心学习以下~~

    首先,我们必须弄清楚的就是C++的名字掩盖规则。在C++中,局部的变量能够掩盖相同名称的全局变量,而这种掩盖对于函数一样起作用。注意这里是名字的掩盖,而不管函数的参数、返回值等其它因素。所以只要名字相同,就会被掩盖。

    接着,就是分清子类与基类作用域的关系。C++中子类作用域被嵌套在基类作用域内。这样,当编译器检查到一个函数名时,首先从最里层作用域开始查找,一层一层向外查找函数,如果找到函数声明,就停止查找。因此,里层的函数会覆盖外层作用域的函数。

    class Base

    {

    private:

           int x;

    public:

           virtual void f1()=0;

           virtual void f2();

           void f3();

           ...

    };

    class Derived: public Base

    {

    public:

           virtual void f1();

           void f4();

           ...

    }

     

    如上面这段代码,类的作用域关系如图。

    现在我们来分析文章开头的程序。

           d.mf1(); //没问题,输出 Derived: mf1() ,因为子类的mf1()函数覆盖了基类的mf1()

           d.mf1(x);//错误! 子类的mf1()覆盖了基类的mf1(int)。名字相同即覆盖,与参数无关

           d.mf2();//没问题,子类继承了基类的mf2()函数,输出Base: mf2()

           d.mf3();//没问题,直接调用子类函数,输出 Derived: mf3()

           d.mf3(x);//错误!子类的mf3()覆盖了基类的mf3()和mf3(double)

           d.mf4();//没问题

    那么,如果想要在子类中既继承基类的函数,同时子类的函数不覆盖基类成员函数,可以使用using声明式。

    在子类中加入下面的using声明式:

           using Base::mf1;

           using Base::mf3; //让基类内名为mf1和mf3的所有东西在子类作用域中都可见,不被覆盖

    然后,我们再使用d.mf1(x); 和d.mf3(x);就没问题了。这时,就继承了基类的成员函数,同时重载函数,并且名字不被覆盖。

     

    使用using声明式将基类的所有同名函数在子类中都可见,但有时候,在私有继承的子类中,我们并不想继承所有这些函数,比如我们只想继承无参数的mf1()函数,这时可以使用转交函数来实现。

    class Derived: private Base

    {

    public:

           virtual void mf1()  //转交函数

           {

                  Base::mf1();  //暗自成为inline

           }

           ...

    }

    转交函数的另一用途就是为那些不支持using声明式的老式编译器使用,将继承而来的名称汇入子类作用域中。

     

    Effective C++:

    Derived classes内的名称会掩盖base classes内的名称。在public继承下一般不希望如此。

    为了让被遮掩的名称再见天日,可使用using声明式或转交函数。

    http://blog.csdn.net/ljinddlj/article/details/1921056

  • 相关阅读:
    XML和解析
    代理模式
    net-snmp配置文件snmp.conf
    tomcat-在eclispe中配置远程调试
    tomcat-在eclipse中配置tomcat容器的内存
    web项目跨域访问
    STS-创建spring配置文件
    STS-新建mvc工程--helloworld
    STS-新建spring mvc项目
    Eclipse-安装Spring Tool Suit 插件
  • 原文地址:https://www.cnblogs.com/liuzongqi/p/3334489.html
Copyright © 2011-2022 走看看