给父类指针调用子类的方法

Call method on subclass given pointer to superclass

本文关键字:方法 子类 调用 父类 指针      更新时间:2023-10-16

我有一组按钮:

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

MyButton是一个QPushButton,继承了QAbstractButton。组中只能选择一个MyButton。

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

MyButton有一个增量方法。

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

我想在当前选择的MyButton实例上调用increment方法。有一个方便的checkedButton()方法,我可以在buttons上调用,但它返回一个指向QAbstractButton的指针。

我不能在指针或QAbstractButton上调用incrementbuttons->checkedButton()->increment();生成error: no member named 'increment' in 'QAbstractButton'。如何增加选中的MyButton?

您只需要让编译器知道您正在使用MyButton*而不是QAbstractButton*,这意味着强制转换。

如果你知道指针是MyButton*,那么你可以直接设置为static_cast<MyButton*>(buttons->checkedButton())->increment();如果你不知道它是否是MyButton*,那么你需要检查一下,这意味着像这样:

MyButton* temp = dynamic_cast<MyButton*>(buttons->checkedButton());
if(temp != nullptr) temp->increment();
编辑:

SaZ指出qobject_castdynamic_cast更可取,因为:

它不需要RTTI支持,它可以跨动态库边界工作

MyButton已经继承自QObject,但还有一个条件,即它与Q_OBJECT一起声明。如果满足这两个条件,那么您可以简单地将dynamic_cast替换为qobject_cast:

MyButton* temp = qobject_cast<MyButton*>(buttons->checkedButton());
if(temp != nullptr) temp->increment();

注意,在QObject派生类的情况下,您可以并且应该使用qobject_cast()而不是动态强制转换。使用Qt元系统可以提高效率。

而且,与动态强制转换不同的是,它可以在没有RTTI的情况下编译,也可以使用动态库。

QAbstractButton动态强制转换为MyButton,并调用increment()

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

为了完整起见,在Qt程序的情况下,你也可以使用信号槽系统:如果increment被声明为slot,那么这将工作:

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