Can I convert an object and access private data in C ++?

I want to access a private data member in a class. There is no member function in the class to access a private data item. This is personal.

I want to take a class, and some - how it opens. One method was to copy the class declaration, make the private member public, and call the new class something_else class. Then I reinterpret and copy the original object. It works. But I want something more elegant ... or maybe something in common ... or just another way.

What are the options? Can i use void *? Can I transfer a class to another empty class? What are the ways to do this?

%

+7
c ++ private member
source share
6 answers

I suppose that

  • You’ve already passed the “encapsulation violation bad” stage,
  • Other possible solutions have been exhausted,
  • Unable to change class title.

There are several ways to undermine access to private members of a class, as shown in GotW # 76 .

  • Duplicate the class definition and add a friend declaration.
  • Use evil macros: #define private public before including the class header.
  • Write a class definition with an identical binary layout and use reinterpret_cast to switch from the source class to the fake one.
  • Specialize the member function of the template, if any (the only portable solution).
+18
source share

With the idea that you propose in your question, you do not need to copy the original object. If you write your own "all public" version of the declaration of a real class, then draw a pointer to this new type, you can directly access the object through it.

The reason none of them is a good idea is simple. You must manipulate the objects of the class that you do not control the source (otherwise you can change the source to give you the access you need). But if you do not control the source, then what if the attendants change the layout of their class? Your duplicate version will no longer match, and the compiler will not be able to detect this mismatch. The result is likely to be memory corruption at runtime.

+3
source share

Since this is misunderstood, I must clarify. All of the following solutions do not require recompiling the object . To use a class in code if it is compiled into an object file, you must include a header file with the declaration of that class.

 #include <class.h> ObjectFoo instance; 

It is possible (but dangerous if you are not careful) to change the title (a) or copy the title to another location and include this title (b), without recompiling the class .

 #include <class_fixed.h> ObjectFoo instance; 

Your code, in which you include the new header, will just think that in the object file (which you did not recompile!) It will find an implementation of the class declared as in class_fixed.h . While the class declared as class.h . If you change member offsets (for example, add new members) to your new heading, you are dead and the code will not work properly. But just changing access works fine. Compiled code does not know about access, it only matters when compiling.

This is not always harmful. In everyday life, you encounter such a change when installing a new version of the library in your system and do not recompile all programs that depend on it. But he should be handled with care.


There are several solutions.

  • memcpy()
    Do not! Not memcpy, since copying objects is sometimes subject to certain policies imposed by the class designer. For example, auto_ptr s cannot just be memcopied: if you memcopy auto_ptr and then the destructor runs for both, you will try to free the same memory twice and the program will crash.

  • Change private: to public: in the header or using a macro. If your license resolves it, you can solve your problem by editing the header file that comes with the class implementation . Whether the source code of the implementation (i.e., the Cpp class file) is under your control does not matter: changing private to public for data members (in the header) is enough and works fine even if you are provided with binary, only a library containing the class definition . (For member functions that change access, its internal name sometimes changes, but for MSVS and GCC this is normal.)

  • Adding a new getter function. Changing private to public almost always normal (unless you rely on specific compile-time checks that should break the compilation if the class has a specific member available) adding a new getter function should be done carefully. The getter function must be built-in (and therefore defined in the class header file).

  • reinterpret_cast
    The effect differs only if you DO NOT throw a pointer to a dynamic base class (dynamic tools) with virtual functions or bases "), the actual instance of which at the time of casting can be obtained from the class in a specific code fragment.

  • protected:
    And just in case you forgot. C ++ can declare protected: members, i.e. Available only for classes derived from this. It can satisfy your needs.

+3
source share

You can, but should not. Objects are just memory. You can, of course, include a pointer in an equivalent class that has the same elements, but where everything is open. But why do you want to do this? Do you have another code that you need to work with? Ask them to add the correct access methods. Do you really need to treat them like public members? Change the class.

I'm not quite sure what you are trying to do, but this is probably a mistake.

+1
source share

I agree with the “edit source” comment, but I think you should add a method, not just comment on 'private'.

You should have a class declaration, so you probably have a title, but maybe not a .cpp / whatever file. Add the built-in member function to the class in the copy of the title and include this title instead of the original. You should still be able to reference the object file for inaccessible source code.

Of course, this is considered a malicious hack, bypassing the protective equipment built into the language, and not working with them. That's why I suggest a minimally evil hack - don't make everything private, and if you can get away with a getter (but without a setter), do it. Of course, the real minimal evil is not to do this, if at all there is a way to avoid it.

Remember that if it is someone from the elses class that you work with, the next version may be implemented in different ways and may not have this member at all.

0
source share

Thanks ... I really wanted to show the code for my original fix. The reason someone was thrilled is because I can't change the source code ... so I have to take a break in prison.


 #include<iostream> using namespace std; // Class Objectfoo // Pretend Objectfoo lives somewhere else ... I cannot open him up class ObjectFoo { private: int datax; public: ObjectFoo() { datax = 100; } void get() { cout << datax << endl;} }; // Class ObjectBar class ObjectBar { public: int datax; }; ObjectFoo FOOEY; ObjectBar* touch_foo(int x, ObjectFoo* foo , ObjectBar* bar) { bar = reinterpret_cast<ObjectBar*>(foo); bar->datax = x; return bar; } int main() { ObjectBar* bar; cout << "Displaying private member in ObjectFoo ie ObjectFoo.datax" << endl; FOOEY.get(); cout << "Changing private member " << endl; bar = touch_foo(5, &FOOEY, bar); cout << "bar->datax = " << bar->datax << endl; cout << "Displaying private member in ObjectFoo ie ObjectFoo.datax" << endl; FOOEY.get(); return 0; } 

It works ... but I think I need something more general ... or more flexible.

%

0
source share

All Articles