我需要实现对私有成员容器的只读访问.如果我返回一个常量引用,是否可以const_cast它并获得对该成员的完全访问权限?使用的技术是什么?
谢谢.
是,只要引用的生命周期不超过返回它的对象的生命周期.如果您必须公开您不想修改的私有成员,这是一个很好的方法.它并非万无一失,但它是用C++实现这一目标的更好方法之一
是的,没有什么可以阻止这一点.没有办法阻止某人随时在C++中丢弃const.这是C++的限制/特性.
一般来说,你应该将const_cast的每次使用标记为bug,除非它包含足够详细的评论,说明为什么它是必要的.
在许多情况下返回const&是一件明智的事情,特别是如果返回的对象很大或无法复制.
关于const_cast,请记住C++中的"私有"访问说明符是对程序员的帮助 - 它不是一种安全措施.如果有人想要访问对象的私有成员,无论你试图做什么来阻止它,它都可以获取它们.
const int &ref = your_object.your_function(); *(int*)&ref = 1234;
不要担心用户做const_casts只是为了打破你的不变量.如果他们真的想破坏你的代码,他们可以在你没有提供内部属性的访问器的情况下.通过返回常量引用,普通用户不会错误地修改您的数据.
封装可以防止错误,而不是间谍活动恶意编码器无论如何都可以打破它,如果他们真的关心并了解环境(编译器).在编译过程中(在我所知的所有编译器中)都失去了约束.一旦编译单元转换为二进制对象,那些对象就不知道const-ness,并且可以利用它来利用它.
// a.h class A { public: A( int a ) : data_( a ) {} int get() const { return data_; } private: int data_; }; // malicious.h class A; void change( A& a, int new_value ); // malicious.cpp // does not include a.h, but redefines an almost exact copy of it class A { public: A( int a ) : data_( a ) {} int get() const { return data_; } int data_; // private removed }; void change( A& a, int new_value ) { a.data_ = new_value; } // main.cpp #include "a.h" #include "malicious.h" int main() { A a(0); change( a, 10 ); std::cout << a.get() << std::endl; // 10 }
虽然上面的代码是不正确的(一个定义规则被破坏,但是对于类A有两个定义),事实是对于大多数编译器,A和Alitious A的定义是二进制兼容的.代码将编译和链接,结果是外部代码可以访问您的私有属性.
既然你知道它,就不要这样做.这将是***的维持痛苦.对于使用API返回对象的私有部分的软件提供向后兼容性而言,微软花费了相当多的钱(共享相同公共接口但更改内部的API的新版本会破坏某些第三方应用程序代码).对于一些广泛可用的软件,提供者(在这种情况下是微软)将经历提供向后兼容性的痛苦,但是对于鲜为人知的应用程序,他们不会,并且突然之前您运行的应用程序将以各种方式失败.
我认为Herb Sutter曾经说过应该"防范墨菲,而不是反对马基雅维利".也就是说,你应该尽一切可能防止错误地使用错误的代码,但是对于故意滥用代码的人你无能为力.
如果有人真的想要破坏你的代码,他们可以,即使它#define private public
包括你的标题之前(因此创建一个ODR违规,但我离题).
所以是的,传回一个const ref很好.
const_cast可以肯定用于获取对成员的完全访问权限.我猜你不能阻止别人,如果他们一心想在脚上射击自己.如果私有成员不重,请考虑返回该变量的副本.