zoukankan      html  css  js  c++  java
  • C++ 继承体系中的名称覆盖

    首先一个简单的样例:

    int x;
    int f()
    {
        double x;
        cin >> x;
        return x;
    }

    在上述代码中。函数f的局部变量x掩盖了全局变量x。这得从 “C++的名字查找机制“说起,首先。在函数f的局部作用域中查找。(甚至是语句块)。假设不存在,到上一层的作用域再进行查找,... 该命名空间中查找,最后是全局作用域。


    在类的继承体系中,名字覆盖问题也是非常困扰的。此处的"名字"但是是函数名,变量名,typedef, enum都能够,此处以函数名为例。

    值得注意的是,Derived的作用域是嵌套在Base作用域中的。


    对于以下的代码:

    class Base
    {
    public:
      //对于C++类中定义的不论什么类型的函数,名字覆盖的规则都是一样的。
      virtual void func1(int x){cout << "func1(int) in Base ..." << endl;}
      void func2(){cout << "func2() in Base ..." << endl;}
      virtual void func3() = 0;
    };
    
    class Derived : public Base
    {
    public:
      void func1() {cout << "func1() in Derived..." << endl;}
      void func2(int x) {cout << "func2(int) in Derived..." << endl;}
      void func3() {cout << "func3() in Derived..." << endl;}
      void func3(int ) {cout << "func3() in Derived..." << endl;}
    };
    
    int main()
    {
      Derived d;
      d.func1(3); //调用失败。

    编译器在Derived的作用域中找到了该函数名字,可是发现调用不匹配,不能通过编译 d.func2(); return 0; }



    Base基类中定义了函数func1 与 func2,在派生类中重写了函数func1,并定义了该函数的重载版本号。

    对于main函数内的调用,见凝视解析。


    编译器在面对函数调用时,首先是在作用域范围内查找该函数名(由内之外)。 假设找到了该函数名之后。编译器便停止查找,開始检查形參与实參的匹配是否合法, 假设不合法,不能通过编译。


    假设要在上述代码中调用 基类中的版本号 func1(int),那么就须要让编译器在看到该函数调用时,第一时间看到base中的该函数名字,因此。using声明攻克了这个难题,在Derived类定义体内部使用using base::func1声明,也就是让Base中的func1函数名字在  ”编译器查找Derived“作用域是可见 。



    using的位置放在哪里???。!!

    非常easy的道理,public继承 意味 ”  is   a   “的关系,那么在Base class中的 public的名称在Derived中也应该是public。

    可是,假设你并不想继承 Base中的全部的函数,仅仅想继承一部分,那么   这就无关于函数名字的问题了。 既然如此。public继承就不应该被使用!


    因此,我会告诉你。使用private继承也许有这种福利。

    如果Derived以private形式继承Base。而Derived中仅仅想要继承Base中的某个特定的函数版本号,那么using已经无论用了,你须要的是其它的技术。

    比如以下的简单样例:

    class Base
    {
    public:
        void func1(){cout << "func1 in Base" << endl;}
    };
    class Derived : public Base
    {
    public:
        void func1()
        {
            Base::func1(); //转交函数,相当于将func1 in Base 转交给func1  in Derived
        }
    };

    最后。在C++的名字查找中。为了避免Base的函数名覆盖,使用using 声明或者转交函数来完毕。


  • 相关阅读:
    Sql Server 2008 为开发带来的新特性
    MSMQ 与ESB
    面向服务架构(SOA)和企业服务总线(ESB)
    IBM网站 构建您的SOA 系列文章
    Visual Studio 2008 和 .NET Framework 3.5 Training Kit
    模式与实践 系列发布WCF Security Guidance 1.0
    跟NHibernate之夏一起学习NHibernate
    ORACLE一些不常用的脚本
    ORACLE已建表能否创建分区
    Access数据库问题锦集
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/5093016.html
Copyright © 2011-2022 走看看