我找到了一个可以通过其对象修改类的私有成员的地方。我想避免这种情况,因为它违反了Encapsulation的C ++规则。
#include <iostream>
using namespace std;
class TClass
{
private:
int i;
public:
int GetVal() { return i; }
};
int main()
{
TClass obj;
int* ptr = (int*)&obj;
*(ptr+0) = 10;
cout<<"Object Value = "<<obj.GetVal()<<endl;
return 0;
}
我试图通过将addressof(&amp;)运算符重载为
来解决这个问题class TClass
{
private:
TClass* operator&() { return this; }
int i;
public:
int GetVal() { return i; }
};
请分享您对此的宝贵想法。
答案 0 :(得分:7)
我不同意指针是“危险武器”的想法。它们只是语言的一部分,是其中不可或缺的一部分。指针本身并没有什么危险 - 唯一危险的是程序员的无知,他们在不知道如何安全地使用它们的情况下使用它们。
关于超载operator&
的问题,我的建议是:不要。
让我们在这里稍微扩大一下这个问题。你并不是真的要求重载operator&
。您真正想知道的是,采用英雄步骤来阻止人们访问您班级中的private
数据成员是否合适?
我说,不,不是。只需创建私有部分private
,然后保留即可。有几个原因。
首先,也许最重要的是,这样做会增加代码复杂性。您编写的每一行代码都是另一个潜在的错误来源。代码越“空间时代”或技术越多,识别和修复所产生的错误就越困难。它还会使您的代码更加脆弱,使您将来编写的代码更有可能破坏您今天所写的内容。
接下来,采取这些步骤是徒劳的。我几乎可以向你保证,无论你采取什么步骤来阻止我修改你班级的private
数据成员,我都能找到一种方法来击败这些措施。 private
就像锁在门上。它的设计并不是为了让那扇门背后绝对安全。确实让诚实的人诚实,并劝阻那些不那么坚定的不诚实的人。一个坚定,熟练的程序员将击败你可以设计的任何锁。
另一个原因是,虽然看起来非常不可能并且非常可疑,但程序员可能会出于正当理由尝试访问private
成员。您无法知道几年后您的代码可能会被使用的所有方式。如果程序员能够找到以合法和安全的方式访问private
的方法(例如,不调用未定义的行为),则不应该阻挡他们。显然,最好只修改你的课而不是这样做。
答案 1 :(得分:1)
人们错过private
的主要观点是它不是出于安全目的,而是来分离界面和实现细节,因此不惜任何代价强制执行它。
换句话说,它是该类用户的安全网;因此,它不是为万无一失而设计的 - 它可以帮助你避免错误,但如果你决心绕过它,C ++不会阻止你。
至于您的解决方案,可以轻松规避它,只需在使用char &
之前转换为&
。
TClass obj;
int* ptr = (int*)&((char &)obj);
(这是std::addressof
通常使用的技巧,标准为guaranteed to work