简体   繁体   中英

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. One MyButton in the group can be selected at a time.

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

MyButton has an increment method.

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

I want to call the increment method on whichever MyButton instance is currently selected. There's a handy checkedButton() method that I can call on buttons , but that returns a pointer to a QAbstractButton.

I can't call increment on the pointer or the QAbstractButton. buttons->checkedButton()->increment(); yields error: no member named 'increment' in 'QAbstractButton' . How can I increment the selected MyButton?

You just need to let the compiler know that you are using a MyButton* rather than a QAbstractButton* , and that means a cast.

If you know that the pointer is a MyButton* then you can just do a 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* 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:

It doesn't require RTTI support and it works across dynamic library boundaries

MyButton already inherits from QObject , but there is one more qualification, that it is declared with Q_OBJECT . If both of these qualifications are met then you can simply replace the dynamic_cast with a qobject_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. It is more efficient by employing the Qt meta system.

Also, unlike the dynamic cast, it will work when compiling without RTTI, and with dynamic libraries as well.

Dynamic cast QAbstractButton to MyButton and call increment() .

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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