29

Could someone explain in as simple terms as possible (or as simple as you would like) what qobject_cast is, what it does and why we would need to cast one class type to another?

Like, I get typecasting in the sense of casting an int as a char or QString maybe to use QMessageBox, but why cast into different classes?

frogatto
  • 28,539
  • 11
  • 83
  • 129
Michael Thomas
  • 443
  • 1
  • 4
  • 8

2 Answers2

47

Before you start learning what qobject_cast is, you would need to know what C++'s dynamic_cast is. Dynamic cast is all about polymorphism.

C++'s dynamic cast uses RTTI (Run Time Type Information) to cast an object. But qobject_cast does this without RTTI.

What is dynamic cast?

For example suppose we've got a car factory function. Like this:

Car* make_car(string brand){
    if(brand == "BMW"){
        return new BmwCar;
    }
    if(brand == "Audi"){
        return new AudiCar;
    }
    return nullptr;
}

Note that BmwCar and AudiCar classes inherit Car class. Using this function we can make different cars only using one function. For example:

string brand;
cin >> brand;
Car *car = make_car(brand);

BmwCar *bmw = dynamic_cast<BmwCar*>(car);
if (bmw != nullptr) {
    cout << "You've got a BMW!";
}

AudiCar *audi = dynamic_cast<AudiCar*>(car);
if (audi != nullptr) {
    cout << "You've got a Audi!";
}

Without dynamic_cast you won't be able to determine if car is a BmwCar or an AudiCar.

What is different between dynamic_cast and qobject_cast?

  • qobject_cast can only be used with QObject derived classes having Q_OBJECT macro.

  • qobject_cast doesn't use RTTI.

frogatto
  • 28,539
  • 11
  • 83
  • 129
28

qobject_cast is same thing as dynamic_cast, but works only for children of QObject. It doesn't require RTTI and it works much faster, because it is not possible to use QObject in multiple inheritance.

Don't hesitate to do self-research and to read some basic things about OOP and C++. Especially about polymorphism. And don't hestiate to read Qt documentation, it contains a lot of easy-to-understand examples.

A resent usage of qobject_cast is getting a pointer to a class inside a slot:

QObject::connect( btn, &QPushButton::clicked, this, &MyClass::onClicked );
void MyClass::onClicked()
{
    // How to get pointer to a button:
    QObject *p = sender();
    // It's QObject. Now we need to cast it to button:
    QPushButton *btn = qobject_cast<QPushButon *>( p );
    Q_ASSERT( btn != nullptr ); // Check that a cast was successfull
    // Now we can use a QObject as a button:
    btn->setText( "We just clicked on a button!" );
}
Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61
  • Thank you for the answer!! I have found the resources that explain how I should use it and what it does, but I haven't found any explanation for when I would use it. I am basically using it because either the example I am emulating has used it or I have been told to use it. In what scenario would I go "I think qobject_cast/dynamic_cast is the way forward" – Michael Thomas May 16 '17 at 07:24
  • 1
    Just added a sample. If you don't understand where to use it - don't use it. It is not nesessary to use all stuff from Qt ;) – Dmitry Sazonov May 16 '17 at 07:25
  • 3
    @MichaelThomas TL;DR: You'll know when you need it. In many cases, properly decoupled code won't ever need it. I consider it a code smell and try to avoid using it gratuitously. That you haven't had a need for it is usually a good sign! Keep it that way. – Kuba hasn't forgotten Monica May 16 '17 at 14:39
  • Great! qobject_cast, a faster version of dynamic_cast, but only applies for QObject. – Zhang Dec 10 '20 at 09:38