Results 1 to 5 of 5

Thread: PIMPL, the 2nd: pure virtual destructor in private base class.

  1. #1
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default PIMPL, the 2nd: pure virtual destructor in private base class.

    Hi,

    I fail to make the destructor of my PIMPL-Private base class pure virtual like QObjectData does. Since I don't know which information about the PIMPL is relevant or not here comes the "full" test case. (Basically at this point mostly equal to Q_DECLARE_PRIVATE...)

    First one is working:

    Qt Code:
    1. #ifndef FOO_H
    2. #define FOO_H
    3.  
    4. #include <QtCore>
    5.  
    6. #define MYXXX_DECLARE_PRIVATE(Class) \
    7. inline Class##Private* d_myxxx_func() { return reinterpret_cast<Class##Private *>(d_myxxx_ptr); } \
    8. inline const Class##Private* d_myxxx_func() const { return reinterpret_cast<const Class##Private *>(d_myxxx_ptr); } \
    9. friend class Class##Private;
    10. #define MYXXX_DISABLE_COPY(Class) \
    11. Class(const Class &); \
    12. Class &operator=(const Class &);
    13. #define MYXXX_DECLARE_PUBLIC(Class) \
    14. inline Class* q_myxxx_func() { return static_cast<Class *>(q_myxxx_ptr); } \
    15. inline const Class* q_myxxx_func() const { return static_cast<const Class *>(q_myxxx_ptr); } \
    16. friend class Class;
    17. #define MYXXX_D(Class) Class##Private * const d = d_myxxx_func()
    18. #define MYXXX_Q(Class) Class * const q = q_myxxx_func()
    19.  
    20.  
    21. //
    22. // Base classes
    23. //
    24.  
    25. class MYXXXPrivateHolder;
    26.  
    27. class MYXXXPrivate
    28. {
    29. protected:
    30. MYXXXPrivate(MYXXXPrivateHolder *p) : q_myxxx_ptr(p) {}
    31. MYXXXPrivateHolder *q_myxxx_ptr;
    32. public:
    33. virtual ~MYXXXPrivate() {qWarning() << Q_FUNC_INFO;} // this is the line!
    34. };
    35.  
    36. class MYXXXPrivateHolder
    37. {
    38. protected:
    39. MYXXXPrivateHolder(MYXXXPrivate *p)
    40. : d_myxxx_ptr(p) {}
    41. ~MYXXXPrivateHolder() {
    42. delete d_myxxx_ptr;
    43. }
    44. MYXXXPrivate *d_myxxx_ptr;
    45. };
    46.  
    47.  
    48. //
    49. // Use case
    50. //
    51.  
    52. class FilePrivate;
    53.  
    54. class File : public QObject, public MYXXXPrivateHolder
    55. {
    56. Q_OBJECT
    57. public:
    58. File(QObject *parent = 0);
    59. ~File() {
    60. qWarning() << Q_FUNC_INFO;
    61. }
    62. private:
    63. MYXXX_DECLARE_PRIVATE(File)
    64. MYXXX_DISABLE_COPY(File)
    65. };
    66.  
    67.  
    68. class FilePrivate : public MYXXXPrivate
    69. {
    70. public:
    71. FilePrivate(File *_file) : MYXXXPrivate(_file) {}
    72. ~FilePrivate() {
    73. qWarning() << Q_FUNC_INFO;
    74. }
    75. private:
    76. MYXXX_DECLARE_PUBLIC(File)
    77. };
    78.  
    79. #endif
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. #include "foo.h"
    2.  
    3. File::File(QObject *parent)
    4. : QObject(parent)
    5. , MYXXXPrivateHolder(new FilePrivate(this)) {}
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. #include "foo.h"
    2.  
    3. int main(int argc, char *argv[])
    4. {
    5. File f;
    6. return 0;
    7. }
    To copy to clipboard, switch view to plain text mode 
    Well, that compiles and gives the expected result:
    Qt Code:
    1. virtual File::~File()
    2. virtual FilePrivate::~FilePrivate()
    3. virtual MYXXXPrivate::~MYXXXPrivate()
    To copy to clipboard, switch view to plain text mode 

    But when I change the marked line to
    Qt Code:
    1. virtual ~MYXXXPrivate() = 0;
    To copy to clipboard, switch view to plain text mode 

    I get the compilation error
    foo.o: In function `FilePrivate::~FilePrivate()':
    make: Leaving directory `/data/dev/asp/testprojekt-build-desktop'
    foo.cpp:(.text._ZN11FilePrivateD2Ev[_ZN11FilePrivateD5Ev]+0xeb): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
    foo.cpp:(.text._ZN11FilePrivateD2Ev[_ZN11FilePrivateD5Ev]+0x1c7): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
    foo.o: In function `FilePrivate::~FilePrivate()':
    foo.cpp:(.text._ZN11FilePrivateD0Ev[_ZN11FilePrivateD5Ev]+0xeb): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
    foo.cpp:(.text._ZN11FilePrivateD0Ev[_ZN11FilePrivateD5Ev]+0x1d7): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
    collect2: ld returned 1 exit status
    make: *** [testprojekt] Error 1

    What do I not see???


    Thanks

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: PIMPL, the 2nd: pure virtual destructor in private base class.

    Virtual destructors must always be implemented even if they are declared pure virtual. By making the MYXXXPrivate virtual destructor pure you are saying that this class is designed to be inherited (virtual) and must be inherited (pure). Using the destructor this way is fine but any derived class will call the abstract class destructor (statically bound) when it is deleted, which is why an implementation is required. The destructor implementation can be empty but will have to be outside the declaration

  3. The following user says thank you to ChrisW67 for this useful post:

    Lykurg (5th April 2012)

  4. #3
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: PIMPL, the 2nd: pure virtual destructor in private base class.

    Hmm, ok, and then why someone would like to do that? (Initial I planned to force derived classes to define/declare their own destructors...)

    I can't the any difference between
    Qt Code:
    1. /* *.h */
    2. virtual ~XXX() = 0;
    3. /* *.cpp */
    4. XXX::~XXX() {}
    To copy to clipboard, switch view to plain text mode 
    and
    Qt Code:
    1. virtual ~XXX {}
    To copy to clipboard, switch view to plain text mode 
    beside the hiding of the implementation, but normal you also don't make the base class of your private classes public...

  5. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: PIMPL, the 2nd: pure virtual destructor in private base class.

    The difference between your two options is that the first prohibits creation of a concrete instance of class XXX (pure virtual), while the second does not.

    To make MYXXXPrivate abstract it has to have at least one pure virtual member function. If the class has no other methods then the only method you can make pure virtual is the destructor (constructors cannot be virtual). The destructor of the base class will be called as part of the destruction of the derived class, which is unlike other member functions in the base class that are only called if the derived class explicitly calls then. You cannot suppress the call to the base class destructor so you must provide an implementation to satisfy the linker.

  6. #5
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: PIMPL, the 2nd: pure virtual destructor in private base class.

    Doh!

    Quote Originally Posted by ChrisW67 View Post
    pure virtual
    I hate that. If I am too focused on one particular problem I loose the bigger picture...

    Thanks for taking me by the hand.

Similar Threads

  1. Replies: 2
    Last Post: 26th November 2011, 04:52
  2. Cost of pure virtual
    By ShaChris23 in forum General Programming
    Replies: 4
    Last Post: 4th November 2007, 18:20
  3. Replies: 3
    Last Post: 14th September 2007, 09:41
  4. inheritance, pure virtual
    By TheKedge in forum General Programming
    Replies: 2
    Last Post: 18th January 2007, 11:20
  5. virtual overloaded functions and base class function call...
    By nouknouk in forum General Programming
    Replies: 7
    Last Post: 11th March 2006, 21:26

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.