zoukankan      html  css  js  c++  java
  • Effective C++ 学习笔记(19)

    避免这样的成员函数:其返回值是指向成员的非const 指针或引用,但成员的访问级别比这个函数要低

      使一个成员为 private 或protected 的原因是想限制对它的访问,对吗?劳累的编译器要费九牛二虎之力来确保你设置的访问限制不被破坏,对不对?所以,写个函数来让用户随意地访问受限的成员没多大意义,对不对?如果你确实认为有意义,那么请反复阅读本段,直到你不这样认为为止。

      实际编程中很容易违反这条规则,下面是个例子:

      

    class Address { ... }; // 某人居住在此
    class Person {
    public:
    Address
    & personAddress() { return address; }
    ...
    private:
    Address address;
    ...
    };

      成员函数 personAddress 为调用者提供的是Person 对象中所包含的Address 对象,但是,也许是出于效率上的考虑,返回结果采用的是引用,而不是值( 见条款22 )。遗憾的是, 这个成员函数的做法有违当初将Person::address 声明为private 的初衷:

      

    Person scott(...); // 为简化省略了参数
    Address& addr = // 假设addr 为全局变量
    scott.personAddress();

      现在,全局对象 addr 成为了scott.address 的另一个名字,利用它可以随意读写scott.address。实际上,scott.address 不再为private,而是public,访问级提升的根源在于成员函数personAddress。当然,本例中给出的address 的访问级是private,如果是protected,情况完全一样。

      不仅仅是引用,指针也会产生以上问题。下面的例子和上面相同,只不过这次用的是指针:

      

    class Person {
    public:
    Address
    * personAddress() { return &address; }
    ...
    private:
    Address address;
    ...
    };
    Address
    *addrPtr =
    scott.personAddress();
    // 问题和上面一样

      而且,对于指针来说,要担心的不仅仅是数据成员,还要考虑到成员函数。因为返回一个成员函数的指针也是有可能的:

      

    class Person; // 提前声明
    // PPMF = "pointer to Person member function"
    // (指向Person 成员函数的指针)
    typedef void (Person::*PPMF)();
    class Person {
    public:
    static PPMF verificationFunction()
    {
    return &Person::verifyAddress; }
    ...
    private:
    Address address;
    void verifyAddress();
    };

      如果你过去没试过象上面那样将成员函数指针和 typedef 结合起来的用法,可能会觉得Person::verificationFunction 的声明有点吓人。别害怕,它的全部含义只不过是:

    • verificationFunction 是一个没有输入参数的成员函数
    • 它的返回值是 Person 类中一个成员函数的指针
    • 被指向的函数(即,verificationFunction 的返回值)没有输入参数且没有返回值,即void。
      至于 static 关键字,当它用于对成员的声明时,其含义是:整个类只有这个成员的一份拷贝,并且这个成员可以不通过类的具体对象来访问。有关static的完整介绍可以参考C++教程。(如果你的C++教程里没有介绍静态成员,请把书页撕了扔到垃圾回收站吧。注意封面一定不要乱扔以免破坏环境。最后,去借或买本更好的教程吧。)
      最后一个例子中,verifyAddress 是一个私有成员函数,这意味着它只是类的一个实现细节,只有类的成员才应该知道它(当然,友员也知道)。但是,由于公有成员函数verificationFunction 返回了指向verifyAddress 的指针,用户就可以做这样的事:
      
    PPMF pmf = scott.verificationFunction();
    (scott.
    *pmf)(); // 等同于调用
    // scott.verifyAddress

      这里,pmf 成了Person::verifyAddress 的同义词,只是有个重要的区别:可以没有限制地使用它。虽然前面说了那么多,有一天你可能为了程序的性能还是不得不写象上面那样的函数--------返回值是某个访问级较低的成员的指针或引用。但同时,你又不想牺牲private 和protected 为你提供的访问限制。这种情况下,你可以通过返回指向const 对象的指针或引用来达到两全其美的效果。


  • 相关阅读:
    project和task
    Gradle的安装
    Spring 集成 RMI
    RMI远程调用
    安装、启动与基本配置
    删除
    文件的分隔与合并
    my27_OGG MySQL To MySQL错误汇总
    1.5 GO json转Map
    1.4 Go语言-switch语句(转)
  • 原文地址:https://www.cnblogs.com/DanielZheng/p/2129578.html
Copyright © 2011-2022 走看看