Please nominate your Qt Champions for 2021!

Cast custom class to QObject

  • Is there a way to get a custom class that inherits from QObject to cast it to a QObject or a way to get a custom class to a generic class? The reason for this is I have created a table model base want it to use a QList<QObject *> and want to pass in other QList<CustomClass *> so the table model class can be generic and I don't have to create a table model class for every table view.

  • I think that templates will help you.

  • I don't know If I'm getting what You want to do right but have a look at qobject_cast.

  • kkrzewniak, as I understood he wants to have some method that can receive as argument list with generic (any class inherited from QObject) type. At this case qobject_cast will not help, but method templating will.

  • Well, you can always assign a derived class pointer to a baseclass pointer. Like:

    QObject* obj = customClassObject;

    That doesn't work for templates though. Still, you can convert a QList<CustomClass*> into a QList<QObject*>:

    @QList<CustomClass*> l1;
    QList<QObject*> l2;
    l2.reserve( l1.size() );
    for ( int i = 0; i < l1.size(); ++i )
    l2.push_back( l1[i] );@

    ..or make the model a template, although that can be become tricky, as QObject and templating doesn't go together well (and QAbstractItemModel is derived from QObject).

    I would also question whether your model data really should be QObjects. Most often it shouldn't, but be modeled as simple value-type classes which can be assigned and copied (a usual beginner's mistake is to make everything a QObject).

  • Normally, I would put other objects to the model, not QObjects. The only thing, where QObject pointers make sense in a model, is, when implementing a property table.

  • Frank, the problem is, that QList<MyCustomClass*> does not have a baseclass pointer QList<QObject*>. Only the pointers inside the list do. That is why Denis suggests to use templates. Using a template, haackers can achieve what he wants.

    @template <class ObjectType>
    void setObjectList(QList<ObjectType*>);

    The above would allow you to pass in any type of QList, for instance. There is much more you can do. With some tricks, you can make sure at compile time that ObjectType inherits QObject and generate a readable errormessage if it doesn't. Or you can make your code even more generic by accepting iterators instead of only lists, so you can pass in any container that provides the right kind of iterator. That would allow you to also use a QVector, a QSet or any other complient container of objects.

    Templates can be way cool, but it is a tricky topic to get into.

  • But that can only work if CustomClass is derived from QObject. Otherwise casting is a bad idea.
    Why don't you put a QList<QObject*> as parameter and store such a parameter in your app?
    Or make a template conversion function with the code from above:
    template<class T>
    QList<QObject*> convert(QList<T*> l1)
    QList<QObject*> l2;
    l2.reserve( l1.size() );
    for ( int i = 0; i < l1.size(); ++i )
    l2.push_back( l1[i] );
    return l2;

    and the call your model lile this:


  • Andre: I know what templates are good for. I think Denis wanted to template the whole model (he didn't talk about converting lists nor mentioned that its possible).

    But thinking about it, I don't really get what all this abstraction and templating is supposed to be good for, in this particular case. Given you don't want to implement a property table, what is the purpose of a generic model on QObjects? And for anything more specific, you'll need to know the type of object anyway, to do anything useful with it. So what's the use case?

  • Frank, I don't know why did you think I talked about whole model template. In this case method templating will be good enough (as Andre showed us).
    About use case. Author asked for this and maybe he has some use case (maybe he just trying to be generic).

Log in to reply