-1

I found somewhere that we can modify private members of a class by its object. I thought to avoid this as it violates the C++ rule of Encapsulation.

#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; 
}

I tried to solve this by overloading addressof (&) operator as,

class TClass
{
  private:
    TClass* operator&() { return this; }
    int i;

  public:
    int GetVal() { return i; }
};

Please share your valuable thought on this.

andand
  • 17,134
  • 11
  • 53
  • 79
  • @RaymondChen: Disagreed -- not a dupe. The link you provide does provide excellent advice which applies to this question here, but it is a completely different question. – John Dibling Dec 13 '13 at 15:48
  • 2
    To be honest, this idea is a bit like not showering in order to keep pickpockets away. – molbdnilo Dec 13 '13 at 15:53
  • @JohnDibling The accepted answer explains why you cannot protect your members against malicious access. – Raymond Chen Dec 13 '13 at 16:46
  • @RaymondChen: I understand that, but just because that answer applies here doesn't mean this question should be closed. – John Dibling Dec 13 '13 at 17:06
  • Closing a question as duplicate doesn't neccessarily mean that the question is bad. After all, you can ask seemingly different questions which boil down to the same answer, and AFAIK it is better to see this, then having "individual" answers appearing as if they were different. Personally I don't really see a reason for the downvotes, but this is something you have to get used to. – Devolus Dec 13 '13 at 17:30

2 Answers2

7

I disagree with the idea that pointers are "dangerous weapons." They are simply a part of the language, and an integral part at that. There's nothing dangerous about pointers themselves -- the only thing that's dangerous is the ignorance of programmers who use them without knowing how to do so safely.

As to your question about overloading operator&, my advice is: don't.

Let's broaden the question a bit here. You're not really asking about overloading operator&. What you're really wondering is if it's appropriate to take heroic steps to prevent people from accessing the private data members in your classes?

I say, no it's not. Just make private parts private, and leave it at that. There are a couple of reasons.

First and maybe foremost, doing so increases code complexity. Every line of code you write is another potential source of bugs. The more "space age" or technical that code is, the more difficult the resulting bugs tend to be to identify and fix. It also makes your code more brittle, making it more likely that code you write in the future will break what you wrote today.

Next, it's futile to take these steps. I can almost guarantee you that no matter what steps you take to prevent me from modifying the private data members of your class, I can find a way to defeat those measures. private is like a lock on a door. It's not designed to make what's behind that door absolutely secure. It's really there to keep honest people honest, and dissuade the less determined dishonest ones. A determined, skilled programmer will defeat any lock you can devise.

Another reason is because, although it seems highly unlikely and extremely dubious, a programmer might try to access the private members for legitimate reasons. You can't know all the ways in which your code might be used years from now. If a programmer can find a way to access the privates in a way that is both legitimate and safe (eg, without invoking undefined behavior), you should not stand in their way. Obviously it would be best to simply modify your class rather than doing this.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • Specifically, overloading `operator&()` can be easily defeated with `std::addressof` whose sole purpose is to get the real address of an object despite some pesky programmer overloading this operator. – SirGuy Dec 13 '13 at 15:40
  • ohh. std::addressof stll can do it – Purushottam Hirave Dec 14 '13 at 09:41
1

The main point that people miss about private is that it's not there for security purposes, but to separate interface and implementation detail, so there's no point in enforcing it at any cost.

In other words, it's a safety net for the user of the class; because of this, it's not designed to be foolproof - it can help you avoid mistakes, but if you are determined to circumvent it C++ won't stop you.

As for your solution, it can be easily circumvented, just cast to char & before using &.

TClass obj;
int* ptr = (int*)&((char &)obj);

(this is the trick normally used by std::addressof, and it is guaranteed to work by the standard)

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • Oh.. that means to avoid the operator& overload on TClass by casting to char& and then, get the address, then casting back to int*. Great!! – Purushottam Hirave Dec 14 '13 at 09:43