Consider the below C++ code
class B;
class A{
private:
B* mB;
};
class B{
private:
doSomethingImportant();
};
We have a Object A that contains (has a) Object B. The parent being A and child being B. Now if I want A to make B do doSomethingImportant() , I see that adding A as a friend of B is the only way to do it.
friend class A
inside class B. This would enable A's functions to access B's private function.
I find this approach a little weird since creates a loophole in the Data_Hiding concept. Is there a better way to establish a parent-child relationship between the object ? or is this the best way ?
Adding my actual motivation for this question
class elevator{
private:
//The Lift box the elevator controls
liftboxControlUnit & mLiftBoxCtrlUnit;
//constructor
elevator(int Level=1, int NoOfBanks =1 );
//Destructor
~elevator();
//Triggers the search to move to the next floor if required
void moveLiftToNext();
public:
//Adds request to the queue
void addRequest(int FloorNumber){
//Add the request to the queue. The single button outside the elevator door
mLiftBoxCtrlUnit.addRequest(FloorNumber);
}
//For Emergency. Should be accessible to everyone !
void setEmergency();
void unsetEmergency();
};
typedef enum Direction{
UP,
DOWN
}direction;
class liftboxControlUnit{
private:
//The request for various floors
set<int> mRequestQueue;
//The various banks for the whole system
vector<Bank> mBanks;
//The total number of levels. Remains the same for one building
const int mTotalLevel;
//Instruction to move the box to certain level
void processRequest(){
//Do the logic to move the box.
}
//can passed to the elevator
void addRequest(int x){
mRequestQueue.insert(x);
}
//Can be set by elevator class
void setEmergency(){
//Do the required
//Set Emergency on all Banks
}
void unsetEmergency(){
//UnsetEmegency on all banks
}
void emergencyListener(){
//Listen to all the banks if emergency has been set
}
void BankFreeListener(){
//Listen to the banks if any is free
//If so then
processRequest();
}
public:
//Constructor
liftboxControlUnit(int TotalLevels, int NoOfBanks): mTotalLevel(TotalLevels){
for(int i=0 ; i lessthan NoOfBanks; ++ i)
mBanks.push_back(Bank(0,UP));
}
friend class elevator;
};
class Bank{
private:
//The dailpad inside the bank
dailpad & mpad;
//Current Location
int mPresentLevel;
//Current direction of movement
direction mDirection;
//Currently moving
bool mEngaged;
//Manipulate the bank
void move(int NoOfMoves){
setEngaged();
//Move the elevator
unsetEngaged();
}
//getters
int getPresentLevel() const;
int getDirection() const;
//setters
void setPresentLevel(int);
void setDirection(direction);
//Manipulate the engaged flag
bool isEngaged() const;
bool setEngaged();
bool unsetEngaged();
//For emergency
void reset();
//Dailpad Listener
void dailpadListener(){
}
public:
Bank(int StartingLevel, direction Direction): mPresentLevel(StartingLevel),
mDirection(Direction),
mEngaged(false),
mpad()
{
}
//For emergency . Should be available for all.
void SetEmergency();
void UnsetEmergency();
bool isEmergency();
friend class liftboxControlUnit;
};
class dailpad{
private:
//Some DS to represent the state . probably a 2D Array.
void renderDisplay();
public:
//Constructor
dailpad();
void getCommand(int x){
//Depending on the value we can do the following
//Make necessary changes to the display
renderDisplay();
}
friend class Bank;
};
IMO, for this task you should probably nest the "lift box" class inside of the controller class:
To the outside world, there need be no evidence that
lift_box
exists at all. It communicates exclusively with thelift_controller
, and all outside communication with alift_box
goes through thelift_controller
.In this case (only
lift_controller
has access to lift_box at all), it seems clear (at least to me) that any operations thelift_controller
may need to invoke on a lift_box should just be made public functions oflift_box
. To enforce nobody else having access tolift_box
, ensure that the definition oflift_box
is in theprivate:
section oflift_controller
.Edit: I should add that quite a bit of the design you've edited into your question above makes little or no sense to me. Just for example, you have things like direction and present level for the bank. Unless I'm completely misunderstanding what you mean by a bank, this seems like a clear error to me -- the bank isn't at a particular level or moving in a particular direction. Rather, each individual elevator in the bank is at some level and (potentially) moving in some direction.