keypressevent и его перегрузка

У меня есть следующий класс, который обрабатывает нажатие клавиши 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, потому что для 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
Спасибо за ответ! Но до конца еще не ясно. Разве моя ситуация не такая же, как если бы в Boo была функция f2(), которая делала бы то же самое, что и f(), то есть cout<<"foo:f\n. Так что не должно быть ничего плохого в том, что объект Boo вызывает эту функцию... - 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