Родитель - ребенок отношения в C++
Рассмотрим приведенный ниже код C++
class B;
class A{
private:
B* mB;
};
class B{
private:
doSomethingImportant();
};
У нас есть объект A, который содержит (имеет) объект B. Родитель - это A, а потомок - B. Теперь, если я хочу, чтобы A заставлял B делать doSomethingImportant (), я вижу, что добавление A в качестве друга B является единственным способом сделать это.
friend class A
внутри класса B. Это позволило бы функциям A получить доступ к закрытой функции B.
Я нахожу этот подход немного странным, поскольку создает лазейку в концепции Data_Hiding. Есть ли лучший способ установить отношения родитель-ребенок между объектом? или это лучший способ?
Добавляя мою актуальную мотивацию на этот вопрос
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;
};
2 ответа
IMO, для этой задачи вам, вероятно, следует вложить класс "lift box" в класс контроллера:
class lift_controller {
class lift_box {
open_doors();
close_doors();
move_to_floor();
};
std::vector<lift_box> bank;
};
Для внешнего мира не должно быть никаких доказательств того, что lift_box
существует вообще. Общается исключительно с lift_controller
и все внешнее общение с lift_box
проходит через lift_controller
,
В этом случае (только lift_controller
имеет доступ к lift_box вообще), кажется ясным (по крайней мере мне), что любые операции lift_controller
может потребоваться вызвать на lift_box должны быть просто обнародованы функции lift_box
, Чтобы никто не имел доступа к lift_box
убедитесь, что определение lift_box
находится в private:
раздел lift_controller
,
Изменить: я должен добавить, что довольно много дизайна, который вы редактировали в свой вопрос выше, имеет для меня мало или вообще не имеет смысла. Например, у вас есть такие вещи, как направление и текущий уровень для банка. Если я не совсем понимаю, что вы подразумеваете под банком, это кажется мне явной ошибкой - банк не находится на определенном уровне и не движется в определенном направлении. Скорее, каждый отдельный лифт в банке находится на некотором уровне и (потенциально) движется в каком-то направлении.
Вы, кажется, хотите class A
чтобы иметь возможность доступа только к одной частной функции в B, B::doSomethingImportant()
и никаких других частных функций.
Это обычно означает, что B::doSomethingImportant()
должен действительно быть публичным. Таким образом, A не сможет получить доступ к другим частным данным членов B.
Кроме того, если вы не хотите, чтобы другие классы имели доступ B::doSomethingImportant()
они не должны содержать указатель на B, а вместо этого содержат указатель на интерфейс (абстрактный суперкласс) B, который не предоставляет B::doSomethingImportant()
,
Или, возможно, другие классы только читают данные из B. В этом случае они могут содержать B const *
который не позволит им позвонить B::doSomethingImportant()
если они не делают const_cast
,