是否可以将const引用返回给私有成员?

时间:2009-03-31 13:46:46

标签: c++ reference const

我需要实现对私有成员容器的只读访问。如果我返回一个常量引用,是否可以const_cast它并获得对该成员的完全访问权限?什么是使用的技术?

感谢。

9 个答案:

答案 0 :(得分:29)

将const引用返回给私有成员

是否安全

是,只要引用的生命周期不超过返回它的对象的生命周期。如果您必须公开您不想修改的私有成员,这是一个很好的方法。它并非万无一失,但它是在C ++中实现这一目标的更好方法之一

是否可以使用const_cast来实际处理成员

是的,你无能为力,以防止这种情况发生。没有办法阻止某人随时在C ++中丢弃const。这是C ++的限制/特性。

一般情况下,你应该将const_cast的每次使用都标记为bug,除非它包含足够详细的评论,说明为什么它是必要的。

答案 1 :(得分:21)

返回const&在许多情况下是一件明智的事情,特别是如果被退回的对象很大或无法复制。

关于const_cast,请记住C ++中的“私有”访问说明符是对程序员的帮助 - 它不是一种安全措施。如果有人想要访问某个对象的私有成员,无论你试图做什么来阻止它,它都可以获取它们。

答案 2 :(得分:10)

const int &ref = your_object.your_function();
*(int*)&ref = 1234;

答案 3 :(得分:7)

不要担心用户做const_casts只是为了打破你的不变量。如果他们真的想破坏你的代码,他们可以在你没有提供内部属性的访问器的情况下。通过返回常量引用,普通用户不会错误地修改您的数据。

Encapsulation prevents mistakes, not espionage如果他们真正关心并了解环境(编译器),恶意编码器无论如何都可以破解它。在编译过程中(在我所知的所有编译器中)都失去了约束。一旦编译单元转换为二进制对象,那些对象就不会知道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和Clitious A的定义是二进制兼容的。代码将编译和链接,结果是外部代码可以访问您的私有属性。

现在你知道了, 不要这样做 。这将是***的维持痛苦。对于使用API​​返回对象的私有部分的软件提供向后兼容性而言,微软花费了相当多的钱(共享相同公共接口但更改内部的API的新版本会破坏某些第三方应用程序代码)。对于一些广泛可用的软件,提供者(在这种情况下是微软)将经历提供向后兼容性的痛苦,但是对于鲜为人知的应用程序,他们不会,并且突然之前您运行的应用程序将以各种方式失败。

答案 4 :(得分:5)

const_cast 绝对可以用于获取对成员的完全访问权限。我猜你不能阻止别人,如果他们一心想在脚上射击自己。如果私有成员不重,请考虑返回该变量的副本。

答案 5 :(得分:5)

我认为Herb Sutter曾经说过应该“防范墨菲,而不是反对马基雅维利”。也就是说,你应该尽一切可能防止错误地使用错误的代码,但是对于那些故意滥用代码的人你无能为力。

如果某人真的想破坏你的代码,他们可以,即使是在#define private public之前包括你的标题(因此产生ODR违规,但我离题)。

所以是的,传回一个const ref就好了。

答案 6 :(得分:1)

是的,所以它可能不是你想要做的。另一方面,如果某人遇到常规问题,那么他们可能真的知道他们在做什么。

答案 7 :(得分:1)

可以获得完全访问权限。但是为了什么?

不要忘记让访问者变得不正确

const MyType& getMyValue() const;

此外,您可以在回调中为您注入私人值。

void doJob( callback c )
{
    c( myPrivateValue_ );
}

答案 8 :(得分:0)

根据史考特·迈耶(Scott Meyer)的书Effective C++(请参阅第28条),您应该避免使用它。这是项目28的摘录:

  

这就是为什么任何将句柄返回到内部部分的函数的原因   该物体很危险。手柄是否为   指针,引用或迭代器。 这无关紧要   符合const 的条件。成员函数是否重要   返回句柄本身就是const。重要的是   返回句柄,因为一旦完成,就运行   句柄可能会超过它所引用的对象的风险。

相关问题