5

I have class A that has a pointer to an instance of the pure virtual class B. Class C is derived from B and will automatically have a pointer to A (which is its parent), and needs to access its members. This can be achieved by adding friend class C inside class A, though then this is needed for every class that will derive from B.

Code example:

class A
{
public:
    friend class B; // This does not allow derived classes to be friends
    friend class C; // Now derived class B has access to `DoDomething`, but then this is needed for every single derived class

private:
    void DoDomething();
};


class B
{
    virtual void Tick() = 0;

protected:
    A* m_pointerToA; // <- is being set upon creating automatically
};


class C : public class B
{
    virtual void Tick()
    {
        m_pointerToA->DoSomething();
    }
};

Is there a way to make all derived classes from B have access to private and protected members of class A that they are pointing to, without having to add friend class X for each of them?

Broxzier
  • 2,909
  • 17
  • 36
  • 3
    `friend`ing isn't derived, you can't. – πάντα ῥεῖ Nov 23 '15 at 21:22
  • @πάνταῥεῖ Then I'm stuck with having to either make `A`'s members and methods public, or befriending every derived class I assume? – Broxzier Nov 23 '15 at 21:25
  • 1
    @Broxzier No you are not, because `B` can expose the functionality that needs friendship to its derived classes through protected member functions of its own. – Sergey Kalinichenko Nov 23 '15 at 21:26
  • 1
    @Broxzier I've provided a "little" workaround [here](http://stackoverflow.com/questions/27492132/how-can-i-remove-refactor-a-friend-dependency-declaration-properly) how to get rid of friend relationships and replace them with interfaces. – πάντα ῥεῖ Nov 23 '15 at 21:31
  • @πάνταῥεῖ That's very interesting, I'll definitely give abstract interfaces a go. Thanks! – Broxzier Nov 23 '15 at 21:44

1 Answers1

6

Since friendship is not inherited, you need to wrap all the functionality that relies on friendship into protected functions of the base class B. This will let all classes deriving from B access the functionality of A that needs "befriending":

class B {
    virtual void Tick() = 0;
protected:
    A* m_pointerToA; // <- is being set upon creating automatically
    void callDoSomething() {
        m_pointerToA->DoSomething();
    }
};


class C : public class B {
    virtual void Tick() {
        std::cout << "Class C is about to tick..." << std::endl;
        callDoSomething();
    }
};

class D : public class B {
    virtual void Tick() {
        callDoSomething();
        std::cout << "Class D has just ticked!" << std::endl;
    }
};

This effectively localizes the area where the friendship is used in your class hierarchy to class B, which helps with encapsulation.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523