简体   繁体   English

给子类的指针上的调用方法给出超类的指针

[英]Call method on subclass given pointer to superclass

I have a set of buttons in a group: 我在一组中有一组按钮:

buttons = new QButtonGroup();

button_0 = new MyButton("A", this);
button_1 = new MyButton("B", this);
button_2 = new MyButton("C", this);

MyButton is a QPushButton, which inherits QAbstractButton. MyButton是一个QPushButton,它继承了QAbstractButton。 One MyButton in the group can be selected at a time. 一次可以选择一个MyButton。

MyButton::MyButton(const QString &text, QWidget *parent)
    : QPushButton(text, parent)
{
    this->setCheckable(true);
    this->setChecked(false);
}

MyButton has an increment method. MyButton有一个增量方法。

void MyButton::increment()
{
    this->j++;
}

I want to call the increment method on whichever MyButton instance is currently selected. 我想在当前选择的任何MyButton实例上调用增量方法。 There's a handy checkedButton() method that I can call on buttons , but that returns a pointer to a QAbstractButton. 我可以在buttons调用一个方便的checkedButton()方法,但是该方法返回一个指向QAbstractButton的指针。

I can't call increment on the pointer or the QAbstractButton. 我不能在指针或QAbstractButton上调用increment buttons->checkedButton()->increment(); yields error: no member named 'increment' in 'QAbstractButton' . 产生error: no member named 'increment' in 'QAbstractButton' How can I increment the selected MyButton? 如何增加所选的MyButton?

You just need to let the compiler know that you are using a MyButton* rather than a QAbstractButton* , and that means a cast. 您只需要让编译器知道您使用的是MyButton*而不是QAbstractButton* ,这意味着QAbstractButton*

If you know that the pointer is a MyButton* then you can just do a static_cast<MyButton*>(buttons->checkedButton())->increment(); 如果您知道指针是MyButton*则只需执行static_cast<MyButton*>(buttons->checkedButton())->increment(); If you don't know if its a MyButton* then you'll need to check, and that'll mean something like this: 如果您不知道它是否为MyButton*则需要进行检查,这意味着类似以下内容:

MyButton* temp = dynamic_cast<MyButton*>(buttons->checkedButton());

if(temp != nullptr) temp->increment();

EDIT: SaZ has pointed out that qobject_cast is preferable to dynamic_cast because: 编辑: SaZ指出 qobject_castdynamic_cast更可取,因为:

It doesn't require RTTI support and it works across dynamic library boundaries 它不需要RTTI支持,并且可以跨动态库边界工作

MyButton already inherits from QObject , but there is one more qualification, that it is declared with Q_OBJECT . MyButton已经继承自QObject ,但还有另一个限定条件,即它是使用Q_OBJECT声明的。 If both of these qualifications are met then you can simply replace the dynamic_cast with a qobject_cast : 如果同时满足这两个条件,则可以简单地用qobject_cast替换dynamic_cast

MyButton* temp = qobject_cast<MyButton*>(buttons->checkedButton());

if(temp != nullptr) temp->increment();

Note that in the case of QObject derived classes, you can and should use qobject_cast() instead of dynamic cast. 请注意,对于QObject派生类,您可以并且应该使用qobject_cast()而不是动态qobject_cast() It is more efficient by employing the Qt meta system. 通过使用Qt元系统,效率更高。

Also, unlike the dynamic cast, it will work when compiling without RTTI, and with dynamic libraries as well. 另外,与动态转换不同,它在不带RTTI以及动态库的情况下也可以工作。

Dynamic cast QAbstractButton to MyButton and call increment() . 动态将QAbstractButtonMyButton并调用increment()

QAbstractButton* abstractButton = buttons->checkedButton();
MyButton* myButton = dynamic_cast<MyButton*>(abstractButton);
if (myButton)
{
    myButton->increment();
}

为了完整起见,对于Qt程序,您还可以使用信号插槽系统:如果将increment声明为slot则可以使用:

QMetaObject::invokeMethod(abstractButton, "increment");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM