1

以下の C++ コードを検討してください

class B;

class A{
private:
    B* mB;
};

class B{

private:
    doSomethingImportant();

};

オブジェクト B を含む (持つ) オブジェクト A があります。親は A で、子は B です。A に B をdoSomethingImportant()させたい場合、Aを B の友人として追加することが唯一の方法であることがわかります。それをするために。

friend class Aこれにより、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;
};
4

2 に答える 2

1

IMO、このタスクでは、おそらくコントローラークラス内に「リフトボックス」クラスをネストする必要があります。

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_box へのアクセス権しかありません) 、lift_box で呼び出す必要があるlift_controller操作はすべて のパブリック関数にする必要があることは (少なくとも私には) 明らかです。に誰もアクセスできないようにするには、 の定義がのセクションにあることを確認してください。lift_controllerlift_boxlift_boxlift_boxprivate:lift_controller

編集:上記の質問に編集したデザインのかなりの部分が、私にはほとんど、またはまったく意味がないことを追加する必要があります。たとえば、銀行の方向性や現在のレベルなどがあります。あなたが言っている銀行の意味を完全に誤解していない限り、これは明らかな誤りのように思えます。銀行は特定のレベルにあるわけでも、特定の方向に動いているわけでもありません。むしろ、バンク内の個々のエレベーターは、あるレベルにあり、(潜在的に) ある方向に動いています。

于 2011-11-02T03:54:37.827 に答える
0

class AB の 1 つのプライベート関数にのみアクセスでき、他のプライベート関数にはアクセスできないようにしたいようですB::doSomethingImportant()

これは通常、B::doSomethingImportant()実際に公開する必要があることを意味します。このように、A は B の他の非公開データ メンバーにアクセスできなくなります。

さらに、他のクラスに にアクセスさせたくない場合はB::doSomethingImportant()、それらは B へのポインターを保持するのではなく、 を公開しない B のインターフェイス (抽象スーパー クラス) へのポインターを保持する必要がありますB::doSomethingImportant()

あるいは、他のクラスは B からデータを読み取るだけかもしれません。そのB const *場合B::doSomethingImportant()const_cast.

于 2011-11-02T03:42:57.830 に答える