Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
July 28, 2014
arrowPress Releases
July 28, 2014
PR Newswire
View All
View All     Submit Event





If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 
Accessing privates without 'friend'(c++)
by Ofer Rubinstein on 01/05/10 04:14:00 pm   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

[ 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.

 


Related Jobs

Integrated Military
Integrated Military — Remote Work Possible, Florida, United States
[07.27.14]

Software Engineer
Cloud Imperium Games
Cloud Imperium Games — Austin, Texas, United States
[07.25.14]

DevOps Engineer
Cloud Imperium Games
Cloud Imperium Games — Austin, Texas, United States
[07.25.14]

Animation Programmer
Cloud Imperium Games
Cloud Imperium Games — Austin, Texas, United States
[07.25.14]

Server/Backend Programmer






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.


none
 
Comment: