0

I have a derived class that implements an interface(abstract class) in C++. This interface has a couple of protected functions whose implementation are defined in derived class.

Now I'm trying to access these protected functions in derived class from an external class, by declaring the external class as a friend in derived class. However, the compiler still complains that I cannot access the protected member functions.

For example: I have class ConnectSession implementing IConnectSession. And an external class called SystemProcess who wants to access protected member function HandlePriviledgedRequest.

In IConnectSession.h

class IConnectSession{
protected:
    virtual void HandlePriviledgedRequest() = 0;
}

In ConnectSession.h

class ConnectSession : public IConnectSession{
protected:
    void HandlePriviledgedRequest() override {/* func definition */}
    friend class SystemProcess;
}

In friend class I try to access HandlePriviledgedRequest()

SystemProcess.cpp

SystemProcess::ApplyConfiguration(){
    std::shared_ptr<IConnectSession> sessionPtr = new ConnectSession();
    sessionPtr->HandlePriviledgedRequest(); // compile error
}

It throws an error from compiler saying I cannot access protected members even if I have already declared SystemProcess as a friend. Since friend declarations are not inherited I particularly declare them in ConnectSession. Why does it not work and how to fix it? Thanks.

Vince
  • 81
  • 4
  • In general, I’d expect member functions of an interface to be public. Why are these protected? – Pete Becker Feb 13 '19 at 22:10
  • @PeteBecker, I would like to make sure some interface methods are only called within certain classes but not in others. So the friend membership is only granted to those certain classes. – Vince Feb 13 '19 at 22:53

2 Answers2

2

That's because your access is thru the IConnectSession interface, sessionPtr, and your friendship is only with the derived class, not the base class.

Bo R
  • 2,334
  • 1
  • 9
  • 17
2

Access control is something that only applies at compile time. In

SystemProcess::ApplyConfiguration(){
    std::shared_ptr<IConnectSession> sessionPtr = new ConnectSession();
    sessionPtr->HandlePriviledgedRequest(); // compile error
}

even though sessionPtr gets set to an instance of ConnectSession, its static type is IConnectSession and that is what access control is ran against. Since SystemProcess isn't a friend of IConnectSession it is not allowed to access HandlePriviledgedRequest().

You'll need to make it a friend of IConnectSession to get it to compile.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Thank you. This makes sense. Is it a best practice to declare friend class in both base class and derived class?? – Vince Feb 13 '19 at 21:50
  • @Vince Best practice is to normally avoid friend classes as the break encapsulation and normally mean there is a tight coupling between things. In this case though you only need to be a friend of the base since you are only accessing the interface that is provided by the base class. You would need to be a friend of the derived class if you need to cast the base to the derived to access derived only potions. – NathanOliver Feb 13 '19 at 21:54