2

This question has already been asked here -- more than twice, actually --, but I myself haven't been able to derive a solution to my problem from the posts.

What I have is a library, with, among others, a class named A in it. From class A I need to access an std::map<>, but it is private. Also, and based on the possibilities I found in the post I mentioned, class A has no templated function.

I'm actually able to recompile the library, so that I could simply change the visibility. However, that would be a lot of work -- and I'm not sure if changing the visibility won't get anything else to crash.

What I'd like to do is, in a class B:

// NOT MY CODE -- library <a.h>
class A {
private:
    std::map<int, int> A_map;
};

// MY CODE -- module "b.h"
# include <a.h>
class B : private A {
public:
    B() {
        for (auto it(A_map.begin()); it != A_map.end(); ++it) {
            ...;
        }
    }
};

How may I do it without changing the original class -- and without having any available templated method in the base class for to be overloaded/specialized?

Community
  • 1
  • 1
Rubens
  • 14,478
  • 11
  • 63
  • 92
  • 3
    What is `template std::map map;`? – Andy Prowl Feb 26 '13 at 22:24
  • @us2012 How would private inheritance help in this case? – juanchopanza Feb 26 '13 at 22:26
  • 2
    @us2012 I have no problem with using `class B : private A`, but it still won't let me access `map` from `A`. – Rubens Feb 26 '13 at 22:27
  • it all depends on class A's functionality and what you want the access for. however, in the last gasp, see [Johannes' technique for accessing private parts](http://stackoverflow.com/a/3173080/464581) in the question you linked to. it's now sort of classic – Cheers and hth. - Alf Feb 26 '13 at 22:27
  • @AndyProwl It's just a map, it could be anything -- but a method, actually. – Rubens Feb 26 '13 at 22:28
  • @juan, Rubens: Sorry, I totally misread the question. – us2012 Feb 26 '13 at 22:28
  • 4
    my blog shows a way to do that. please dont use the implementation linked in my answer. better use http://bloglitb.blogspot.de/2011/12/access-to-private-members-safer.html if it works for you – Johannes Schaub - litb Feb 26 '13 at 22:28
  • @JohannesSchaub-litb I've seen your blog and post two, but I haven't really been able to reproduce what you've done. I'll try it once more! – Rubens Feb 26 '13 at 22:31
  • 1
    @DrewDormann: He meant it could be anything but a method, I believe – Andy Prowl Feb 26 '13 at 22:36
  • @DrewDormann, AndyProwl Yes, sorry if I wasn't clear. It's actually an `std::map<>`, storing something that does not really matter, like two `int`s. The fact here is that class `A` also have members, but none of them are `template <> function()`, which stops me from using the solution from the post I've mentioned. I'll be trying @JohannesSchaub-litb post once more, and make an edit adding what I fail to reproduce. – Rubens Feb 26 '13 at 22:40
  • @JohannesSchaub-litb Man, I'm really lost here. I don't even know where to modify your code to get something close to what I want. What is all that magic adventure with the `A_f` and `Rob` structs? My c++ understanding stops way before reaching that code ^^ Would you mind to post some directives? (: – Rubens Feb 26 '13 at 23:55
  • 1
    i recommend a new SO question if you wanna know how the "safer" second post on my blog works. im pretty sure there are many ppl happy to explain it on SO. – Johannes Schaub - litb Feb 27 '13 at 09:54
  • @JohannesSchaub-litb Hope I've been able to describe my problem *concisely* [here](http://stackoverflow.com/questions/15110526/allowing-access-to-private-members). – Rubens Feb 27 '13 at 11:09

4 Answers4

3

You should first be very confident that what you're trying to do is actually valid... there's probably a good reason that variable is private. Modifying it may break the state of an instance of A, and there's no guarantee a private variable will be in a logical or consistent state when you break encapsulation to read it.

With that caveat, if you can modify / recompile the library declaring your class a friend of A is probably the way to go. Have B hold an instance of A by composition, and since it's a friend it can access private members of the A instance.


And, because I'm feeling particularly evil here's a demo of how to break encapsulation without even modifying A. Although it's not portable (I'm working in g++ on 64-bit linux) and involves figuring out the in-memory object layout. I changed the map to a vector for simplicity.

#include<vector>
#include<iostream>

class A {
private:
    int blah; //Just to make it a bit more realistic.
    std::vector<int> A_vec;
public:
    void outputVec() {
       std::vector<int>::iterator it = A_vec.begin();
       while(it != A_vec.end()) {
         std::cout << *it << std::endl;
         ++it;
        }
    }
};


int main() {
  A* a = new A();
  std::vector<int>* v = (std::vector<int>*)(((char*)a)+sizeof(long));
  v->push_back(27);
  v->push_back(12);
  a->outputVec();
  return 0;
}
patros
  • 7,719
  • 3
  • 28
  • 37
  • Thanks for the post; I've made a minor edit to my question. I don't really mind about visibility politeness here -- I know what I'm doing, and all I'm doing is reading some numbers I need. The library which I'm using is huge, and still under development by their owners. They'll probably change the way things are done, but they won't do it now -- and I wouldn't like to do it too. – Rubens Feb 26 '13 at 22:52
  • @Rubens. The problem is the maintainers of this library are explicitly making no guarantees about the contents of that private member HAVING the numbers you need even in the existing version of the code. I've written plenty of objects that streamed data in and only clean it up into a usable state once it's actively requested by a public accessor. – patros Feb 26 '13 at 23:03
  • @patros I **do** agree with what you are saying, but yet I am aware of what's going on, I'm able to see the entire code here, and the values are available at the point I want to access them. I just would like to avoid changing/recompiling the code. And if there was I modification to do in my code only, I would have it to perfectly suit my program. – Rubens Feb 26 '13 at 23:07
  • @patros +1 Thanks very much for your answer. Everytime my teacher said he was evil I got scared, and the same works here for your post (: Although this is for me an amazingly entertaining solution, I'm afraid I won't be able to use it: not only because figuring out the size of *all* elements preceding the `map` would be tricky, but also due to the fact that I'm running this in a distributed application -- the last thing I want to rely on here is memory alignments ^^ Serialization already washed my head with misaligned bytes (: – Rubens Feb 26 '13 at 23:30
2

Private variables are deliberately protected from any outside access. You can only access members if the owning class permits it via less restrictive access or making friends.

and I'm not sure if changing the visibility won't get anything else to crash.

Access restrictions in C++ are deliberately designed so that accessibility is the last thing checked when doing name lookups. That means if you have a working program and you make something more accessible then the program's behavior shouldn't change at all, because all other potential problems were already checked before checking accessibility.

bames53
  • 86,085
  • 15
  • 179
  • 244
  • I thought of this *opening up visibility only helps*, but I was actually trying to emphasize the fact that I'd like not to mess up with code that I myself haven't written. This would really go as a last resort. – Rubens Feb 26 '13 at 22:44
1

First of all, it is a very good idea to keep all data members private. If your derived class really needs access to A_map, then the best thing to do is to give the base class a getter that returns a const reference to it (assuming you only need read-access). If you need write access to A_map, then that is a good indication that you need to rethink your design.

Other than that, there is no way to grant class B access to A_map without seriously bending the rules and conventions of C++.

By the way, private inheritance means something else. It means that all public methods of class A would become private methods of class B. In other words, private inheritance means that you inherit the implementation of A, but not its interface. So it will not help you here.

Dima
  • 38,860
  • 14
  • 75
  • 115
  • The library isn't mine, and although it works perfectly fine, it is still under development -- and I really would like to avoid doing any modification to the code, as even compiling it takes time. – Rubens Feb 26 '13 at 22:59
0

Private inheritance is really a composition in disguise! It actually means "implemented in terms of".

Putting that aside, irrespective of private/public/protected mode of inheritance, private members would remain private(not accessible outside of that class, even from the derived ones).

There are two legitimate ways to access private members of any class.

1) Access private members using Get/Set methods(assuming the class exposes it).

2) Befriend with the class.

In your case, class A belongs to a library, it is the responsibility of library vendors to provide proper interface for the external world to interact with class A. Perhaps, it is better to have a talk with the library vendor. To me, it looks more like a design issue rather than implementation issue.

Just for testing, as a quick hack, I would suggest befriending mechanism.

    class A {
      friend class B;
      private:
      std::map<int, int> A_map;
    };

    // MY CODE -- module "b.h"
    class B {
     public:
     B() {
      for (std::map<int, int>::iterator  it(a.A_map.begin()); 
          it != a.A_map.end(); ++it) {  }
     }
     A a;
    };
Arun
  • 2,087
  • 2
  • 20
  • 33