Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt Meta-Object System and virtual functions with multiple inheritance - unexpected behaviour
Forum Update on Monday, May 27th 2025

Qt Meta-Object System and virtual functions with multiple inheritance - unexpected behaviour

Scheduled Pinned Locked Moved General and Desktop
12 Posts 4 Posters 7.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    genC
    wrote on 5 Aug 2011, 09:07 last edited by
    #1

    Hello everyone,

    I have a weird problem regarding virtual functions with multiple inheritance and meta-object.
    I have a class, MainClass, that inherits QObject, and an abstract class AbstractClass that doesn't inherit anything. Then, I have a class MyClass that inherits both MainClass and AbstractClass. AbstractClass declares a pure virtual function isAbstractClass(). This function is defined in MyClass.
    I created an instance of MyClass via metaObject.newInstance(), and when I call isAbstractClass(), it doesn't give me the expected result.
    I ran with debugging (see breakpoint location in code below), and stepped into the function. It just jumped to MyClass::metaObject() in moc_MyClass.cpp instead of MyClass::isAbstractClass() in MyClass.cpp...

    If I don't use multiple inheritance (having AbstractClass inherit from MainClass, and MyClass from AbstractClass for instance), it just runs fine.

    Why is it behaving this way? Is it an moc limitation? Are there any solutions? Any help will be greatly appreciated.

    Thanks!

    MainClass.h:
    @#ifndef MAINCLASS_H
    #define MAINCLASS_H

    #include <QObject>
    #include <QMetaObject>
    #include <QVariant>

    class MainClass : public QObject
    {
    Q_OBJECT

    public:
    MainClass();

    virtual ~MainClass();
    

    };

    Q_DECLARE_METATYPE(MainClass*)

    #endif // MAINCLASS_H
    @

    AbstractClass.h:
    @#ifndef ABSTRACTCLASS_H
    #define ABSTRACTCLASS_H

    class AbstractClass
    {
    public:
    AbstractClass();

    virtual bool isAbstractClass() const = 0;
    

    };

    #endif // ABSTRACTCLASS_H
    @

    MyClass.h:
    @#ifndef MYCLASS_H
    #define MYCLASS_H

    #include "MainClass.h"
    #include "AbstractClass.h"

    class MyClass : public MainClass, public AbstractClass
    {
    Q_OBJECT

    public:
    Q_INVOKABLE MyClass();

    bool isAbstractClass() const;
    

    };

    Q_DECLARE_METATYPE(MyClass*)

    #endif // MYCLASS_H
    @

    main.cpp:
    @#include <QtCore/QCoreApplication>
    #include "MyClass.h"
    #include <iostream>

    using namespace std;

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    QMetaObject metaObj = MyClass::staticMetaObject;
    QObject* obj = metaObj.newInstance();
    AbstractClass* ac = (AbstractClass*) obj;
    cout<<ac->isAbstractClass();       // insert breakpoint here. step into function
    
    return a.exec&#40;&#41;;
    

    }
    @

    MainClass.cpp:
    @#include "MainClass.h"

    MainClass::MainClass()
    {
    }

    MainClass::~MainClass()
    {
    }
    @

    AbstractClass.cpp:
    @#include "AbstractClass.h"

    AbstractClass::AbstractClass()
    {
    }
    @

    MyClass.cpp:
    @#include "MyClass.h"

    MyClass::MyClass()
    {
    }

    bool MyClass::isAbstractClass() const {
    return false;
    }
    @

    1 Reply Last reply
    0
    • L Offline
      L Offline
      loladiro
      wrote on 5 Aug 2011, 10:01 last edited by
      #2

      Is this what you need
      @
      class MainClass : public QObject, public virtual AbstractClass
      class MyClass : public MainClass, public virtual AbstractClass
      @ ?

      1 Reply Last reply
      0
      • G Offline
        G Offline
        genC
        wrote on 5 Aug 2011, 10:16 last edited by
        #3

        No, MainClass can only inherit QObject.

        1 Reply Last reply
        0
        • L Offline
          L Offline
          loladiro
          wrote on 5 Aug 2011, 10:31 last edited by
          #4

          Ok, sorry I misunderstood. Your problem is that you're trying to cast you QObject pointer to an Abstract class pointer using C-style casts. That's not only unsafe, but doesn't work in this situation. Since QObject, does not inherit from AbstractClass, you'll have to use dynamic_cast .

          1 Reply Last reply
          0
          • G Offline
            G Offline
            genC
            wrote on 5 Aug 2011, 10:40 last edited by
            #5

            Well actually, the QObject pointer points to a MyClass instance. Since MyClass inherits AbstractClass, I should be able to cast the QObject pointer to a AbstractClass. Am I right?
            But, correct me if I'm wrong, dynamic_cast only succeeds between classes of the same hierarchy (from base class to derived class), so it will fail in my case because AbstractClass doesn't inherit QObject (and I don't want to do it).

            1 Reply Last reply
            0
            • L Offline
              L Offline
              loladiro
              wrote on 5 Aug 2011, 10:45 last edited by
              #6

              Actually int points to the appropriate offset of the QObject class and the compiler doesn't know that it's a MyClass. Since you don't want to use dynamic_cast, you can do:
              @
              AbstractClass* ac = qobject_cast<MyClass*>(obj);
              @

              1 Reply Last reply
              0
              • G Offline
                G Offline
                goetz
                wrote on 5 Aug 2011, 11:30 last edited by
                #7

                dynamic_cast
                is a means of C++ and works for all sorts of class hierarchies (unless RTTI is not switched off)

                qobject_cast
                is provided by Qt and only works on QObject based class hierarchies

                So you can safeley use dynamic_cast for your purpose. But be sure to check the resulting pointer not being a null pointer (in case something went wrong)

                http://www.catb.org/~esr/faqs/smart-questions.html

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  genC
                  wrote on 5 Aug 2011, 13:14 last edited by
                  #8

                  dynamic_cast fails in my case (because QObject and AbstractClass aren't related, I believe). that's why I used c-style cast. But again it seems not to work (because of the whole cast inner working).
                  qobject_cast could've been interesting, but I really need to cast to AbstractClass* rather than MyClass*. And AbstractClass cannot inherit QObject...
                  I found a workaround, but it's very bad design. I created a Interface class that all my abstract classes would inherit (including AbstractClass), and wrote a function that returns an Interface* given QObject*:

                  @Interface* getInterface(QObject* obj) {
                  if (obj == NULL) {
                  return (Interface*) NULL;
                  }
                  std::string name(obj->metaObject()->className());
                  if (name == "MyClass") {
                  return dynamic_cast<MyClass*> (obj);
                  }
                  else {
                  return (Interface*) NULL;
                  }
                  }@

                  This way, the cast succeeds. But since it is completely static, I'd rather find another way.

                  Any suggestions?

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    giesbert
                    wrote on 5 Aug 2011, 13:48 last edited by
                    #9

                    If the QObject subclasses can be of any type and perhaps also derived not directly from QObject, there is no way for that.

                    If dynamic_cast fails, I assume, you have RTTI disabled, at least for Qt it's disabled.

                    Nokia Certified Qt Specialist.
                    Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      goetz
                      wrote on 6 Aug 2011, 23:52 last edited by
                      #10

                      dynamic_cast always works as long as you are navigating within a inheritance hierarchy. It fails only for two reasons:

                      • the object you cast is not of the type you want to cast to
                      • RTTI is switched off

                      As Gerolf already stated, it's most likely the missing RTTI that causes you trouble.

                      If you use QMetaObject to get some class names, you can also use qobject_cast, as the first is available with QObjects only.

                      http://www.catb.org/~esr/faqs/smart-questions.html

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        genC
                        wrote on 8 Aug 2011, 14:23 last edited by
                        #11

                        Sorry for the late reply. I used dynamic_cast in other cases, and it worked. Only in this particular one it doesn't.
                        In case RTTI is disabled, is there a way to enable it?

                        1 Reply Last reply
                        0
                        • G Offline
                          G Offline
                          goetz
                          wrote on 15 Aug 2011, 16:59 last edited by
                          #12

                          For Qt itself that's configured at compile time with the -rtti switch.

                          For your projects, you can add rtti do CONFIG:

                          @
                          CONFIG += rtti
                          @

                          http://www.catb.org/~esr/faqs/smart-questions.html

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved