Assume you have two classes, a Manager
who holds a set of Client
s and the Client
holds a backreference to the Manager
.
class Manager {
public:
void addClient(Client* client) {
m_clients.push_back(client);
client->setManager(this);
}
private:
std::list<Client*> m_clients;
};
class Client {
public:
void setManager(Manager* manager) {
m_manager = manager;
}
private:
Manager* m_manager;
};
The confusing, probably even dangerous feature of this API is that Client exposes a setManager() method that can be called by anyone, yet should only be called by the Manager::addClient() method.
assert(manager->hasClient(this))
in setManager() would prevent wrong calling at runtime, however I would prefer a solution that doesn’t allow the user to call methods he isn’t supposed to call.
What would be common solution? I don’t
- want to use
friend
to expose all of Clients members to Manager so that he can establish the binary connection inaddChild()
- want both classes to share some kind of Composite base class. They should remain unrelated inheritancewise.
2
One fairly standard approach would be to make Client::setManager
protected and declare Manager::addClient
as a friend function in Client
. This will allow Manager::addClient
access to all of Client
‘s private and protected members, not just Client::setManager
, but is more encapsulated overall than a public Client::setManager
.
See also:
- Specify a class member function as a friend of another class?
- What is the use-case to use C++ friend class?
- Should I use friend classes in C++ to allow access to hidden members?
- When should you use ‘friend’ in C++?
- How does the friend keyword (Class/Function) break encapsulation in C++?