Home > Software engineering >  Granting private access to two classes without introducing dependency
Granting private access to two classes without introducing dependency

Time:01-13

I have class, say Rectangle that has a private method Rectangle::paint. I want to let two other classes access this method, and only those two. So, I thought of this:

template <class T, class Q> 
class Rectangle {
    void paint();
    friend T;
    friend Q;
};

Problem is, when I want to instantiate a Rectangle object in T, it means Tneeds to know about Q, either by including a header or by using a forward declaration, both of which I would like to avoid. Also, the other way around regarding Q not knowing about T. Is there a way to do this?

Edit: To clarify a bit, I want to instantiate Rectangle in Foo, but have it mean Rectangle<Foo, Bar> so that Bar could access private members from elsewhere. I don't want Foo to know about Bar or vice versa.

Thanks

CodePudding user response:

If Rectangle is a template and parametrized on Q and T, then Q and T are part of the type. You cannot use Rectangle<Q,T> without "knowing" about Q or T.

How about this:

template <size_t> struct rectangle;

template <size_t tag>
struct rectangle_modifier { 
    void paint(rectangle<tag>&);
};

template <size_t tag>
struct rectangle {
    friend rectangle_modifier<tag>;
    private:
    void paint() {}
};

template <size_t tag> 
void rectangle_modifier<tag>::paint(rectangle<tag>& r) {r.paint(); }


struct foo : rectangle_modifier<1> {};
struct bar : rectangle_modifier<1> {};



int main () {
    rectangle<1> r;
    foo{}.paint(r);
    bar{}.paint(r);
}
       

foo and bar need not know anything about each other. They both can paint a rectangle<1>. The tag is because you said you want to have different rectangles that each let two different classes access their paint.

Note that this is rather intrusive (foo and bar must inherit), not sure if this is a problem.

Its also not safe in the sense that anybody can write another class that inherits from rectangle_modifier<1> to access rectangle<1>::paint. However, thats not really what private is for. private is to restrict accidential access and to make clear that one should not access it. It is not to prevent by all means that it can be accessed. If someone wants to hack it, they will find a way.

Actually I would simply make rectangle::paint public and call it a day. Encapsulation is to make sure invariants don't break. Painting a rectangle that can be painted does not break an invariant.

  • Related