我有一个上课的班级,它处理转义键。

         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),它将无法正常工作。根据docs的keyPressEvent(QKeyEvent * event)方法是QWidget的受保护方法。
  因此,初始代码只是重载了该方法,不是吗?和过载工作。但是,为什么使用另一个名称但具有相同实现的方法的全新版本将不起作用?

最佳答案

它不是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的已编译代码无法对其进行调用。

07-24 09:44
查看更多