ctkPimpl.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /**
  2. \class ctkPimpl ctkPimpl
  3. \brief Utility macros for handling private implementations. It is in addition
  4. to QtGlobal: Q_DECLARE_PRIVATE, Q_DECLARE_PUBLIC,
  5. Q_D and Q_Q.
  6. Application code generally doesn't have to be concerned about hiding its
  7. implementation details, but when writing library code it is important to
  8. maintain a constant interface, both source and binary. Maintaining a constant
  9. source interface is easy enough, but keeping the binary interface constant
  10. means moving implementation details into a private class. The PIMPL, or
  11. d-pointer, idiom is a common method of implementing this separation. ctkPimpl
  12. offers a convenient way to connect the public and private sides of your class.
  13. \section start Getting Started
  14. Before you declare the public class, you need to make a forward declaration
  15. of the private class. The private class must have the same name as the public
  16. class, followed by the word Private.
  17. \subsection pub The Public Class
  18. Generally, you shouldn't keep any data members in the public class without a
  19. good reason. Functions that are part of the public interface should be declared
  20. in the public class, and functions that need to be available to subclasses (for
  21. calling or overriding) should be in the protected section of the public class.
  22. To connect the private class to the public class, include the
  23. Q_DECLARE_PRIVATE macro in the private section of the public class.
  24. Additionally, you must construct the d_ptr pointer in the constructor of the
  25. public class.
  26. \subsection priv The Private Class
  27. As mentioned above, data members should usually be kept in the private class.
  28. This allows the memory layout of the private class to change without breaking
  29. binary compatibility for the public class. Functions that exist only as
  30. implementation details, or functions that need access to private data members,
  31. should be implemented here.
  32. To define the private class, nothing special needs to be done, except if you
  33. want the private class to have access to the public class. Then use
  34. Q_DECLARE_PUBLIC and create a public class pointer member. The constructor of
  35. the private class should take a public class reference as a parameter.
  36. \section cross Accessing Private Members
  37. Use the Q_D() macros from functions in
  38. the public class to access the private class. Similarly, functions in the
  39. private class can invoke functions in the public class by using the Q_Q()
  40. macro.
  41. */
  42. #ifndef __ctkPimpl_h
  43. #define __ctkPimpl_h
  44. // Qt includes
  45. #include <QtGlobal>
  46. /*! \relates ctkPimpl
  47. * Define a public class constructor with no argument
  48. *
  49. * Also make sure the Pimpl is initalized
  50. */
  51. #define CTK_CONSTRUCTOR_NO_ARG_CXX(PUB) \
  52. PUB::PUB(): d_ptr(new PUB##Private) \
  53. { \
  54. }
  55. /*! \relates ctkPimpl
  56. * Define a public class constructor with one argument
  57. *
  58. * Also make sure the Pimpl is initalized
  59. */
  60. #define CTK_CONSTRUCTOR_1_ARG_CXX(PUB, _ARG1) \
  61. PUB::PUB(_ARG1 _parent) \
  62. : Superclass( _parent ) \
  63. , d_ptr(new PUB##Private) \
  64. { \
  65. }
  66. /*! \relates ctkPimpl
  67. * Define the setter in the public class.
  68. *
  69. * This should be put in the .cxx file of the public class. The parameter are
  70. * the name of the public class (PUB), the type of the argument to return (_TYPE),
  71. * the name of the getter(_NAME) and the name of the variable in the Private class(_VARNAME).
  72. */
  73. #define CTK_SET_CXX(PUB, _TYPE, _NAME, _VARNAME) \
  74. void PUB::_NAME(_TYPE var) \
  75. { \
  76. Q_D(PUB); \
  77. d->_VARNAME = var; \
  78. }
  79. /*! \relates ctkPimpl
  80. * Define the setter in the public class.
  81. *
  82. * This should be put in the .cxx file of the public class. The parameter are
  83. * the name of the public class (PUB), the type of the argument to return (_TYPE),
  84. * the name of the setter(_NAME) and the name of the variable in the Private class(_VARNAME).
  85. */
  86. #define CTK_GET_CXX(PUB, _TYPE, _NAME, _VARNAME) \
  87. _TYPE PUB::_NAME()const \
  88. { \
  89. Q_D(const PUB); \
  90. return d->_VARNAME; \
  91. }
  92. #endif