Results 1 to 5 of 5

Thread: MOC and macro expanding

  1. #1
    Join Date
    Aug 2015
    Posts
    3
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default MOC and macro expanding

    I know that Qt4 moc was not able to do macro expanding, and now Qt5 moc can do it, at least partly.
    I have macro for simple signals adding to multiple classes, lets say, for errors and warnings reports.

    Qt Code:
    1. #define ERROR_SENDER \
    2. signals: \
    3. void error(Errors::ErrorCodes errorCode);
    4.  
    5. #define WARNING_SENDER \
    6. signals: \
    7. void warning(Warnings::WarningCodes warningCode);
    8.  
    9. #define ERROR_AND_WARNING_SENDER \
    10. ERROR_SENDER \
    11. WARNING_SENDER
    To copy to clipboard, switch view to plain text mode 

    And, in another header:

    Qt Code:
    1. class Compressor : public QObject
    2. {
    3. Q_OBJECT
    4.  
    5. ERROR_AND_WARNING_SENDER
    6.  
    7. ...
    8. }
    To copy to clipboard, switch view to plain text mode 

    But it doesn't work. If I expand macro myself with simple copy-paste, it works, and signals are added in moc-generated file. But if I use macro, signals are not added in moc-generated file and it results in
    ./debug/compressor.o: In function `ZN10Compressor8openFileERK7QString6QFlagsIN9QIODe vice12OpenModeFlagEE':
    compressor.cpp:40: undefined reference to `Compressor::error(Errors::ErrorCodes)'


    How to fix it?

  2. #2
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: MOC and macro expanding

    I don't know about macros, but you can use a simple base class to do that:
    Qt Code:
    1. class Notifier : public QObject{
    2. Q_OBJECT
    3. signals:
    4. void error(Errors::ErrorCodes errorCode);
    5. void warning(Warnings::WarningCodes warningCode);
    6. };
    7.  
    8.  
    9. class Compressor : public Notifier
    10. {
    11. Q_OBJECT
    12. }
    To copy to clipboard, switch view to plain text mode 
    It is much cleaner and now it is easier to add new functionality to all the signal-sending objects in the hierarchy. It will work in both Qt4 and Qt5 too.
    If you have a lot of common code, macros will get messy very quickly.
    Another thing, does it really make sense for an object to be an "error sender" without being a "warning sender" ? If something can report an error, surely it should be able to report a warning.
    Anyway, I'd go for common functionality via base class instead of macros.

  3. #3
    Join Date
    Aug 2015
    Posts
    3
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: MOC and macro expanding

    but you can use a simple base class to do that
    That was my first idea before creating any macros. The problem is that Qt classes don't support multiple inheritance from QObject-based classes. More correctly, there can be only one QObject-based parent and it should be first one in inheritance ierarchy. Lets say I use that Notifier class you suggested, and I have two other classes:
    class A : public QMainWindow
    and
    class B : public QDialog
    I want them both use my error() and warning() signals, connected to single object who shows user all errors and warnings from the whole program. However, I can't inherit from Notifier and QMainWindow or Notifier and QDialog - they are both based on QObject already.
    Another thing, does it really make sense for an object to be an "error sender" without being a "warning sender" ? If something can report an error, surely it should be able to report a warning.
    Its for possible future program expanding. However, it will not work with a single macro anyway.

  4. #4
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: MOC and macro expanding

    You can use composition instead of inheritance (so the mainWindow or dialog instance "contains" a notifier object).
    If you want to stick to inheritance, then the "Notifier" class does not have to be QObject-based:
    Qt Code:
    1. // helper class used to maintain the connections
    2. class NotifierHelper : public QObject{
    3. Q_OBJECT
    4. signals:
    5. void error(Errors::ErrorCodes errorCode);
    6. void warning(Warnings::WarningCodes warningCode);
    7. };
    8.  
    9. // "error reporting" base class, not based on QObject
    10. class Notifier
    11. public:
    12. void error(Errors::ErrorCodes errorCode){
    13. this->_sender.error(errorCode); // you can invoke signals directly, like method calls (in fact they are methods)
    14. }
    15. void addErrorReceiver(QObject * receiver, const char * signal_or_slot){
    16. QObject::connect(&_sender, SIGNAL(error(Errors::ErrorCodes)), receiver, signal_or_slot);
    17. }
    18. private:
    19. NotifierHelper _sender;
    20. };
    21.  
    22.  
    23. class Compressor : public Notifier
    24. {
    25. Q_OBJECT
    26. public:
    27. void functionWithError(){
    28. SomeReceiver receiver;
    29. this->addErrorReceiver(&receiver, SLOT(receiveError(ErrorCodes)));
    30. // now the 'receiver' object will get the error signal
    31. this->error(Errors::SomeErrorCode);
    32. }
    33. }
    To copy to clipboard, switch view to plain text mode 
    There exists quite a lot of object-oriented programming languages without the macro expansion feature. Just imagine how would you solve this problem in one of these languages.

  5. The following user says thank you to stampede for this useful post:

    kert (6th August 2015)

  6. #5
    Join Date
    Aug 2015
    Posts
    3
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: MOC and macro expanding

    You can use composition instead of inheritance (so the mainWindow or dialog instance "contains" a notifier object).
    Yes, but I don't like it. It's kind of "OOP-hack" for me, because architecturally it is inventing another class and making another object when you just want to make base class realise an interface.
    If you want to stick to inheritance, then the "Notifier" class does not have to be QObject-based
    It is an encapsulation of composition. Looks like I will use this, though it's not OOP-pure. Yes, macros are not pure too
    There exists quite a lot of object-oriented programming languages without the macro expansion feature. Just imagine how would you solve this problem in one of these languages.
    Using interfaces?

    Going to composition-inheritance combination, thank you.

Similar Threads

  1. Qt connect without SLOT macro
    By webstar in forum Qt Programming
    Replies: 2
    Last Post: 20th April 2014, 14:07
  2. Qt usage macro
    By Momergil in forum Qt Programming
    Replies: 3
    Last Post: 15th July 2013, 07:26
  3. Q_OBJECT macro - what exactly does it do?
    By magland in forum Qt Programming
    Replies: 3
    Last Post: 26th September 2007, 10:30
  4. Macro
    By comlink21 in forum Qt Programming
    Replies: 1
    Last Post: 25th July 2007, 11:28
  5. Macro used for debugging
    By sunil.thaha in forum General Programming
    Replies: 11
    Last Post: 30th March 2007, 17:32

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.