zoukankan      html  css  js  c++  java
  • 成员函数查找[条款24]---《C++必知必会》

    调用一个成员函数,涉及三个步骤:第一步,编译器查找函数的名字;第二部,从可用候选者中选择最佳匹配函数;第三步,检查是否具有访问该函数的权限。

    #include<iostream>
    using namespace std;
    
    class B{
    public:
        void f(double para){
        cout<<"B::f"<<para<<endl;
        }
    };
    class D:public B{
    //void f(int para){}; //私有成员,编译main中 d.f(12.3)行,会报错
    public: void f(int para){ cout<<"D::f"<<para<<endl; } }; class E:public D{ int f; }; int main() { D d; d.f(12.3); //输出D::f12 E e; e.f(12.3); //错误 return 0; }

    分析:

      步骤1:查找函数的名字。因为我们正在调用一个D对象的成员,所以将从D的作用域开始查找并且立即定位到D::f上。

      步骤2:从可用的候选者中选择最佳的匹配函数。我们只有一个候选者D::f(为什么只是一个,往后面看),因此会尝试匹配该函数。可以通过将实参12.3从double转换为int而做到这一点(这是合法的,但通常不是我们想要的,因为那样会丢失精度)。

      步骤3:检查访问权限。我们(可能)会得到一个错误,因为D::f是私有成员。

    基类中的哪一个看上去有着更好的匹配、并且可访问的函数f已经无关紧要,因为一旦在内层作用域中找到一个,编译器就不会到外层作用域中继续查找该名字。内层作用域中的名字会隐藏外层作用域中相同的名字。在这一点,C++不同于Java。Java中,内层作用域的方法名字和外层作用域中同名方法属于重载关系。

      实际上,改名字甚至不是一个函数的名字:

    class E:public D{
        int f;
    };
    //...
        E e;
        e.f(12.3); //错误
     

    反思:

      在这个例子中,我们得到一个编译器错误,因为在作用域E中查找名字f,结果找到了一个数据成员,而不是成员函数。顺便说一下,这也是建立并遵从简单的命名诸多理由之一。如果数据成员E::f被命名为 f_ 或者 m_f,它就不会隐藏被继承的基类函数 f 了

  • 相关阅读:
    系列化与反系列化
    改造一下C# Substring()函数
    在C#后端处理一些结果然传给前端Javascript或是jQuery
    ASP.NET MVC传送参数至服务端
    MySQL 操作命令梳理(3)-pager
    MySQL 操作命令梳理(2)-alter(update、insert)
    redis持久化策略梳理及主从环境下的策略调整记录
    php-redis扩展模块安装记录
    centos下部署redis服务环境及其配置说明
    Iptables 规则用法小结
  • 原文地址:https://www.cnblogs.com/azbane/p/8535129.html
Copyright © 2011-2022 走看看