سؤال

ونقول لكم وتصميم C ++ وضع النوافذ المكتبة. قد أو قد لا توفر API رد، لكنه يحتاج إلى توفير API الاقتراع لتسهيل طراز عملي البرمجة.

وماذا تبدو API الاقتراع مثل؟

تحليل بعض الخيارات

أسلوب SDL

struct Event {
    enum { MousePress, KeyPress } type;
    union {
        struct { Point pos; MouseButton b; } mousePress;
        struct { Modifiers mods; char key; } keyPress;
    };
};
void userCode() {
    for(;;) {
        Event e; if(pollEvent(&e)) {
            switch(e.type) {
                case MousePress: cout<<event.mousePress.pos.x; break; // not typesafe
                case KeyPress: cout<<event.keyPress.key; break;
            }
        }
    }
}

نمط الدولة

struct Input {
    enum { Mouse, Keyboard, Nothing } whatChanged;
    MouseButtonsBitfield pressedButtons;
    bool keysPressed[keyCount];
};
void userCode() {
    for(;;) {
        Input in = pollInput();
        switch(in.whatChanged) {
            // typesafe yay
            case Mouse: cout << "is LMB pressed? " << bool(in.pressedButtons&LeftButton); break;
            case Keyboard: cout << "is A pressed? " << in.keysPressed['A']; break;
        }
    }
}

متعة وظيفية الزائفة C ++ أسلوب

struct Event {
    // transforms listener by notifying it of event,
    // returns transormed listener. nondestructive.
    template<class Listener> // sadly invalid, templates can't be virtual.
                                              // a solution is to make Listener the base
                                              // of a hierarchy and make Listener::handle virtual
                                              // but then we're forced to use imperative style
    virtual Listener transform(Listener const&) =0;
};
struct MousePress : Event { // yay we're extensible via inheritance
    template<class Listener>
    virtual Listener transform(Listener const& listener) {
        return listener.handle(*this); // calls the MousePress overload
    }
    Point pos; MouseButton b;
};
struct KeyPress : Event {
    template<class Listener>
    virtual Listener transform(Listener const& listener) {
        return listener.handle(*this); // calls the KeyPress overload
    }
    Modifiers mods; char key;
};
struct NoEvent : Event {
    template<class Listener>
    virtual Listener transform(Listener const& listener) {
        return listener.handle(*this);
    }
};
struct UserWidget {
    UserWidget handle(NoEvent) {
        return UserWidget();
    }
    UserWidget handle(MousePress p) {
        return (UserWidget) { string("pressed at")+lex_cast<string>(p.pos)) };
    }
    UserWidget handle(KeyPress k) {
        return (UserWidget) { string("pressed key=")+lex_cast<string>(k.key)) };
    }
    string pendingOutput;
};
void userTick(UserWidget const& w) {
    cout<<w.pendingOutput;
    userTick(pollEvent().transform(w));
}
void userCode() {
    userTick(UserWidget());
}

وأجوبة لغات أخرى من C ++ لا بأس، إذا كانت توفر فكرة مثيرة للاهتمام.

لا يوجد تعليقات على التغليف الرجاء - نعم الميادين العامة ينبغي أن تكون حقا من يمكنهم الدخول، غادرت أنه من أجل الوضوح

.
هل كانت مفيدة؟

المحلول

لإجابة عن سؤالك بسرعة، لكنني أفضل البساطة في "مدونة على غرار SDL". ويرجع ذلك أساسا قليلا أكثر تعقيدا "نمط الدولة" ذاكرة النفايات وتشتري لك شيئا على الإطلاق (انظر أدناه)، والإعادة في طريقتك للتعذيب "الوظيفي الزائفة C ++" سيتم تجاوز مكدس في أجزاء قليلة من الثانية.

على "الدولة ستايل" : في الخاص بك "ياي typesafe" في رمز "نمط الدولة" لا مبرر له قليلا. كنت لا تزال البت فيها الأعضاء على الوصول استنادا على switch على عضو آخر، لذلك رمز لديه كل نفس نقاط الضعف التي رمز "SDL نمط" له - عن أي خطأ التي يمكن أن تجعل مع رمز على غرار SDL الذي يؤدي إلى تفسير الذاكرة كنوع من الخطأ، هل نقع في خطأ سيئة على قدم المساواة من الوصول إلى عضو uninitialised مع رمز على غرار الدولة.

<القوي> "الوظيفي الزائفة C ++ أسلوب" : لأنت الآن الحصول على مكان ما، وراثة أنواع الأحداث مختلفة من نوع حدث القاعدة. من الواضح أن العودية سخيفة تحتاج إلى أن تصبح حلقة، وهناك عدد قليل من الأشياء الصغيرة لترتيب (على ما أظن 3 طرق لديك اسمه transform() في UserWidget تريد أن يسمى handle()، وأنا أخمن أن تتمكن من حل مشكلة أي قالب الظاهري طرق استخدام Boost.Function أو ما شابه). وأعتقد أن هذا النهج المحتملين، على الرغم من أنني يفضلون البساطة في الاسلوب SDL.

ولكن الأهم: السؤال الأول الحاجة إلى واجهة الاقتراع. هل هناك سبب لماذا pollEvent() لا يمكن منع؟ كما هو عليه، كل شرائح كود 3 وحرق الوقت CPU تفعل شيئا 99.99٪ من الوقت.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top