Now that I've said my piece on inheritance, here's something that might help with your real question, i.e. how to get around the potential problems with friendship.
The way I do this is to create a pure interface for accessing data I want to share with my "friends". I then implement this interface privately, so nobody can access it directly. Finally I have some mechanism that allows me to pass a reference to the interface only to those select classes that I want to allow.
For example:
// This class defines an interface that allows selected classes to
// manipulate otherwise private data.
class SharedData
{
public:
// Set some shared data.
virtual void SettorA(int value) = 0;
// Get some shared data.
virtual bool GettorB(void) const;
};
// This class does something with the otherwise private data.
class Worker
{
public:
void DoSomething(SharedData & data)
{
if (data.GettorB() == true)
{
data.SettorA(m_id);
}
}
private:
int m_id;
};
// This class provides access to its otherwise private data to
// specifically selected classes. In this example the classes
// are selected through a call to the Dispatch method, but there
// are other ways this selection can be made without using the
// friend keyword.
class Dispatcher
: private SharedData
{
public:
// Get the worker to do something with the otherwise private data.
void Dispatch(Worker & worker)
{
worker.DoSomething(*this);
}
private:
// Set some shared data.
virtual void SettorA(int value)
{
m_A = value;
}
// Get some shared data.
virtual bool GettorB(void) const
{
return (m_B);
}
int m_A;
bool m_B;
};
In this example, the SharedData is an interface that determines what can be done with the data, i.e. what can be set, and what is get-only. The Worker is a class that is allowed access to this special interface. The Dispatcher implements the interface privately, so having access to a Dispatcher instance doesn't give you access to the special shared data, but the Dispatcher has a method that lets Workers get access.