My Message close
GAME JOBS
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
May 23, 2013
 
Off Base Productions
Senior Front End Software Engineer
 
Off Base Productions
Web Application Developer
 
CCP - North America
Senior Character Concept Artist
 
Edge of Reality
LEVEL ARTIST
 
CCP - North America
Lead/Senior Visual Effects Artist
 
CCP - North America
Senior Technical Artist
spacer
Blogs

  Accessing privates without 'friend'(c++)
by Ofer Rubinstein on 01/05/10 04:14:00 pm   Featured Blogs
14 comments Share on Twitter Share on Facebook RSS
 
 
The following blog was, unless otherwise noted, independently written by a member of Gamasutra's game development community. The thoughts and opinions expressed here are not necessarily those of Gamasutra or its parent company.

Want to write your own blog post on Gamasutra? It's easy! Click here to get started. Your post could be featured on Gamasutra's home page, right alongside our award-winning articles and news stories.
 

[ From Pompi Dev Blog

Here is a neat little way I found to make one class access the privates of another class, without using friend or direct inheritance. Take a look at this code:

class A {
    public:
        class Observer {
             protected:
                 int GetPrivate(A & a) {return a.ValueA;};
        };
    private:
        int ValueA;
};
class B: public A::Observer {
    public:
        void Foo (A & a) {
             Do something with GetPrivate(a);
        }
};

 

Class B cannot access the privates of class A directly, but it inherits a subclass of A that can access the privates of A given as a parameter. Since I have just tried this "pattern" recently, I am not sure what is the direct benefit of this.

I believe a benefit can be in the sense of making a programmer's life easier. Programming languages play several parts. They provide us powerful functionality, but they also suppose to give us ease of use. You can program anything on assembly, but it would be really difficult to write a big game in assembly. If you do not expose privates via a getter, you give the programmer one less method to think about when he need to use the class's instance for something.

Can you think how you would use this "pattern"? Do you think there is no use for it? Tell me what you think.

 

 
 
Comments

Tyler Glaiel
profile image
seems like extra boilerplate when you could just make it public, or friend

Stephen Northcott
profile image
I'd agree with Tyler. It's interesting from a geeky perspective though.



By the way, some of us *have* written "big game[s] in assembly".

You youngsters don't even know you're born. ;)

Javier Arevalo
profile image
Be real Stephen, "big" doesn't mean the same now as it did back then. :)



It's a cute trick Ofer, it allows more granularity for exposing internals than the all-or-nothing "public, private or friend", since you can write multiple Observers for different sets of private members. Most programmers won't be anal enough to want to use it, but it's there for the taking.

Michael C
profile image
i can't find a reason to disagree with tyler, in as much as i can't find any apparent benefits over using friends.



but i prefer this:



class A {

private:

class Observer {

public:

Observer(A &refA) : refA(refA) {}

int GetPrivate() { return refA.v; }

private:

A &refA;

};



public:

Observer GetObserver() { return Observer(*this); }



private:

int v;

};



i'm not sure why the subclass B is necessary.

Ofer Rubinstein
profile image
Javier said it better, it allows more granularity for exposing internals.

Michael C, I don't completly follow your example, but I think it is equivalent to having a public getter of the private variable.

The trick I showed allows to expose part of the internals(friend expose all the internals) to part of the classes(getter expose it to everything).

Of course you could work around it, but a programming language is not all about functionality, it's also about concepts, abstraction and informality.

This is how I understand it.

Michael C
profile image
my idea was to provide a read-only version of an object -- that is, to be able to pass out instances of A::Observer instead of A, to restrict who is able to modify A.

Paul Hope
profile image
Why not just use interface classes instead so that you can maintain polymorphism and still specialize access specification.

Ofer Rubinstein
profile image
Ahh, ok Michael. But this is quite different than what I was doing.

Paul, sometimes you have two classes which can't inherit each other, but you want to access each other's privates.

I have thought about it more, I think this is useful. In the sense that 'private' is useful. You could write a program without any private members, right? If you take any existing C++ program, and replace all 'private:' with 'public:', the program will still compile and have the same functionality. But will it be the same?

Michael C
profile image
hi ofer,

i'm more curious about what you originally intended. i guess i was thinking about it invertedly -- providing restricted access when the default is read/write. but it seems like providing direct read access to private members is rep. exposure, which is dangerous. i'm curious whether you have any specific cases where to use this.

Paul Hope
profile image
I personally have tried to stay away from inheritance unless the base class is an interface or abstract base class. Here's a code example using the above technique yet pretty much does the same thing as your compositional observer class. I'd like to get some opinions going on the two styles. One last thing is that there can be many types of EntityInterfaces that can be created for different types of specialized access to Entity. This can be useful for different types of frogs ect...





class EntityInterface

{

public:

EntityInterface() { }

virtual ~EntityInterface() { }



virtual int GetHealth() const = 0;

};



class Entity : public EntityInterface

{

public:

Entity( const int& aHealth = 25 ) : health( aHealth ) { }

~Entity() { }

protected:

int GetHealth() const { return health; }

private:

int health;

};







class Frog

{

public:

Frog() { }

~Frog() { }

int GetHealth( const EntityInterface& entity )

{ return entity.GetHealth(); }

};



#include

using namespace std;



int main()

{

Entity entity;

Frog frog ;

int health = frog.GetHealth( entity );

cout << health << endl;

return 0;

}

Ofer Rubinstein
profile image
@Paul Hope, your code is very similar. However, you must pass the interface as parameter. In my code I pass the desired class itself, that also mean I can pass it by value.



What is important to say is, there is no holy grail here. I suggested to do something in a specific way. There are many ways to do the same thing in programming. Usually there is no one way which is better than all other to all the situations.

Coding is also a matter of convineice rather than just functionality. Eventually, you should choose what you feel comfortable with.

I came across this "pattern" when I wanted to wrap two DX interface, in which I had to call the private of one class with the private of the other class as a parameter. This is the context I thought about this.



Again, you write code not only for the computer, you also write it in a way that will be easy for you to handle it.

Paul Hope
profile image
I really like your pattern and will put it into my toolbox, however originally I was confused about the naming of the accessor class to "Observer".



This is because the observer pattern is a different pattern all together used mainly for callbacks in input handlers etc...



I think an alternative is to have 2 classes one called Accessor and the other called Mutator and then only inherit whatever is required depending on the situation.



The other problem I see is if you have one class that needs access to 2 separate Accessor classes then the syntax is not as simple due to ambiguity.



ie:



class A {

public:

class Accessor {

protected:

int GetPrivate(const A& a) const {return a.ValueA;};

};

private:

int ValueA;

};



class B {

public:

class Accessor {

protected:

int GetPrivate(const B& b) const {return b.ValueA;};

};

private:

int ValueA;

};



class C: public A::Accessor, public B::Accessor {

public:

void Foo (A & a) {

cout << A::Accessor::GetPrivate( a );

}



void Foo(B & b) {

cout << B::Accessor::GetPrivate( b );

}

};

Ofer Rubinstein
profile image
Hi Paul,



Yea, I guess observer wasn't the best name. Also, you don't have to call the method GetPrivate, it was a name I picked because class A had no actual meaning. But specifying the classes to differentiate between the accessors can also work. Like you did.

Thanks.

Jonathan Arsenault
profile image
Meh that's is the kind of thing one will do in Java because he cannot use the friend keyword, it is usually referred to as the "Friend accessor pattern".


none
 
Comment:
 




 
UBM Tech