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

本文讨论了在C++中返回私有成员的引用或指针导致访问级提升的问题,并提供了通过返回指向const对象的指针或引用来解决的方法,确保访问限制不受影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

            使一个成员为 private 或 protected 的原因是想限制对它的访问,所以写个函数来让用户随意地访问受限的成员没多大意义。所以,如果有个公有函数,返回指向成员的非const指针或引,成员一般是私有的,那这样就相当于把私有成员暴露给外部接口。

         举例如下:

       

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,情况完全一样。

       总结:本来Address address是私有成员,但是因为成员函数 personAddress() 返回了私有成员的引用,所以,address不再为private,而是public,所以,访问级得到了提升。

        

       不只是返回指向成员的引用会提升访问级,返回指向成员的非const指针也会引发这种问题

       不仅仅是引用,指针也会引发这种问题;

      

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

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

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

       最后一个例子中,verifyAddress 是一个私有成员函数,这意味着它只是类的一个实现细节,只有类的成员才应该知道它(当然,友员也知道) 。但是,由于公有成员函数 verificationFunction 返回了指向 verifyAddress 的指针,用户就可以做这样的事:  

PPMF pmf = scott.verificationFunction();
(scott.*pmf)(); //  等同于调用
// scott.verifyAddress
这里,pmf 成了 Person::verifyAddress 的同义词,只是有个重要的区别:
可以没有限制地使用它。

      

       虽然前面说了那么多,有一天你可能为了程序的性能还是不得不写象上面那样的函数-------- 返回值是某个访问级较低的成员的指针或引用。但同时,你又不想牺牲 private 和 protected 为你提供的访问限制。这种情况下,你可以通过返回指向 const 对象的指针或引用来达到两全其美的效果。详细介绍参见条款 21。


       总结:

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

       2、你又不想牺牲 private 和 protected 为你提供的访问限制。这种情况下,你可以通过返回指向 const 对象的指针或引用来达到两全其美的效果。限制对成员的修改,但还是可以读成员,对成员的访问,只要不修改成员变量就可以接受。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值