เหตุการณ์การกดปุ่มและการโอเวอร์โหลด

ฉันมีคลาสต่อไปนี้ซึ่งจัดการการกดปุ่ม Escape

         class KeyPress : public QWidget
       {
           Q_OBJECT
          public:
            KeyPress(QWidget * parent=0);

          protected:
             void keyPressEvent(QKeyEvent * event);

       };

และไฟล์ .cpp:

          void KeyPress::keyPressEvent(QKeyEvent *event)
           {

                if (event->key() == Qt::Key_Escape) {
                    qApp->quit();
                           }
            }

มันใช้งานได้ดี แต่หากฉันเปลี่ยนชื่อวิธีการ เช่น keyPressed(QKeyEvent * event) มันจะไม่ทำงาน วิธีการ keyPressEvent(QKeyEvent * event) ตามเอกสารเป็นวิธีการที่ได้รับการป้องกันที่ QWidget ดังนั้นโค้ดเริ่มต้นก็โอเวอร์โหลดวิธีการนั้นใช่ไหม และการโอเวอร์โหลดก็ใช้งานได้ แต่เหตุใดเวอร์ชันใหม่ของวิธีการที่มีชื่ออื่นแต่การใช้งานแบบเดียวกันจึงไม่ทำงาน


person parsecer    schedule 30.04.2016    source แหล่งที่มา


คำตอบ (1)


ไม่ใช่ overload แต่เป็น override ของฟังก์ชัน virtual อ่านเกี่ยวกับฟังก์ชัน c++ virtual

ตัวอย่างเช่น:

#include <iostream>

using std::cout;
struct Foo { /*virtual*/void f() { cout << "foo:f\n"; } };
struct Boo : public Foo { void f() { cout << "boo:f\n"; } };

int main()
{
    Boo boo;
    Foo *ptr = &boo;
    ptr->f();
}

พิมพ์โค้ดดังกล่าว foo:f เนื่องจาก for ptr->f() คอมไพเลอร์สร้างสิ่งนี้:

address_of_function = &Foo::f;
call address_of_function

แต่หากคุณไม่ใส่เครื่องหมายข้อคิดเห็น virtual ในโค้ดตัวอย่างของฉันจะพิมพ์ boo:f เนื่องจาก virtual ทำให้คอมไพเลอร์สร้างคล้ายกับโค้ดดังกล่าว:

 address_of_function = ptr->virtual_table_of_Foo_class[offset_of_f]
 call address_of_function

ptr ชี้ไปที่ตารางเสมือนของคลาส Boo และ address_of_function จะเท่ากับ &Boo::f นี่คือวิธีการทำงานของฟังก์ชัน virtual

ดังนั้นในกรณีของคุณ Foo == QWidget และมีโค้ดเช่นนี้อยู่ภายใน Qt:

this->keyPressEvent();

ซึ่งรับที่อยู่ keyPressEvent ในตารางเสมือนและเรียกมันว่า แน่นอนว่าถ้าคุณใช้ KeyPress::someOtherFunction มันจะไม่ถูกเรียก เนื่องจากโค้ดที่คอมไพล์แล้วของ Qt ไม่มีการเรียกมัน

person fghj    schedule 30.04.2016
comment
ขออภัยนั่นคือสิ่งที่ฉันหมายถึง หมายถึงการแทนที่ การใช้งานฟังก์ชันของพาเรนต์ที่แตกต่างกัน ลายเซ็นเดียวกัน แต่คำถามยังคงอยู่ เหตุใดวิธีการใหม่จึงไม่ได้ผล? - person parsecer; 01.05.2016
comment
ขอบคุณสำหรับการตอบกลับ! แต่มันก็ยังไม่ชัดเจนนัก สถานการณ์ของฉันไม่เหมือนกับว่ามีฟังก์ชัน f2() ใน Boo ซึ่งจะทำสิ่งเดียวกันกับ f() ซึ่งก็คือ cout<<"foo:f\n หรือไม่ ดังนั้นจึงไม่น่าจะมีอะไรผิดปกติกับ Boo object ที่เรียกใช้ฟังก์ชันนั้น... - person parsecer; 01.05.2016
comment
แต่ Qt รู้เพียงเกี่ยวกับ Foo::f และเมื่อเหตุการณ์อินพุตของผู้ใช้ถูกจัดการ Qt โทรเท่านั้น โทรเท่านั้น มันสามารถโทรได้เพียง Foo::f เนื่องจากไม่มีความคิดเกี่ยวกับ Boo::f2 - person fghj; 01.05.2016
comment
คอมไพเลอร์สร้างการเรียกฟังก์ชันตามชื่อของฟังก์ชัน ไม่ใช่เนื้อหาของฟังก์ชัน - person fghj; 01.05.2016