ctkPimpl.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. /**
  15. \page CorePimpl CTK Pimpl Macros
  16. \brief Utility macros for handling private implementations. It is in addition
  17. to QtGlobal: Q_DECLARE_PRIVATE, Q_DECLARE_PUBLIC,
  18. Q_D and Q_Q.
  19. Application code generally doesn't have to be concerned about hiding its
  20. implementation details, but when writing library code it is important to
  21. maintain a constant interface, both source and binary. Maintaining a constant
  22. source interface is easy enough, but keeping the binary interface constant
  23. means moving implementation details into a private class. The PIMPL, or
  24. d-pointer, idiom is a common method of implementing this separation. ctkPimpl
  25. offers a convenient way to connect the public and private sides of your class.
  26. \section start Getting Started
  27. Before you declare the public class, you need to make a forward declaration
  28. of the private class. The private class must have the same name as the public
  29. class, followed by the word Private.
  30. \subsection pub The Public Class
  31. Generally, you shouldn't keep any data members in the public class without a
  32. good reason. Functions that are part of the public interface should be declared
  33. in the public class, and functions that need to be available to subclasses (for
  34. calling or overriding) should be in the protected section of the public class.
  35. To connect the private class to the public class, include the
  36. Q_DECLARE_PRIVATE macro in the private section of the public class.
  37. Additionally, you must construct the d_ptr pointer in the constructor of the
  38. public class.
  39. \subsection priv The Private Class
  40. As mentioned above, data members should usually be kept in the private class.
  41. This allows the memory layout of the private class to change without breaking
  42. binary compatibility for the public class. Functions that exist only as
  43. implementation details, or functions that need access to private data members,
  44. should be implemented here.
  45. To define the private class, nothing special needs to be done, except if you
  46. want the private class to have access to the public class. Then use
  47. Q_DECLARE_PUBLIC and create a public class pointer member. The constructor of
  48. the private class should take a public class reference as a parameter.
  49. \section cross Accessing Private Members
  50. Use the Q_D() macros from functions in
  51. the public class to access the private class. Similarly, functions in the
  52. private class can invoke functions in the public class by using the Q_Q()
  53. macro.
  54. \section example Example
  55. Header file (ctkFooObject.h):
  56. \code
  57. // Qt includes
  58. #include <QObject>
  59. // CTK includes
  60. #include "ctkCoreExport.h"
  61. class ctkFooObjectPrivate;
  62. class CTK_CORE_EXPORT ctkFooObject: public QObject
  63. {
  64. public:
  65. ctkFooObject(QObject* parent = 0);
  66. virtual ~ctkFooObject();
  67. void setProperty(double property);
  68. double property()const;
  69. protected:
  70. QScopedPointer<ctkFooObjectPrivate> d_ptr;
  71. private:
  72. Q_DECLARE_PRIVATE(ctkFooObject);
  73. Q_DISABLE_COPY(ctkFooObject);
  74. };
  75. \endcode
  76. Implementation file (ctkFooObject.cpp):
  77. \code
  78. // CTK includes
  79. #include "ctkFooObject.h"
  80. class ctkFooObjectPrivate
  81. {
  82. public:
  83. void processSomething();
  84. double MyProperty;
  85. };
  86. ctkFooObject::ctkFooObject(QObject* parentObject)
  87. : d_ptr(new ctkFooObjectPrivate)
  88. {
  89. Q_D(ctkFooObject);
  90. d->MyProperty = 10.;
  91. }
  92. void ctkFooObject::setProperty(double newProperty)
  93. {
  94. Q_D(ctkFooObject);
  95. d->MyProperty = newProperty;
  96. }
  97. double ctkFooObject::property()const
  98. {
  99. Q_D(const ctkFooObject);
  100. return d->MyProperty;
  101. }
  102. \endcode
  103. */
  104. #ifndef __ctkPimpl_h
  105. #define __ctkPimpl_h
  106. // Qt includes
  107. #include <QtGlobal>
  108. /*!
  109. * \ingroup Core
  110. * @{
  111. */
  112. /*!
  113. * Define a public class constructor with no argument
  114. *
  115. * Also make sure the Pimpl is initalized
  116. * \see \ref CorePimpl
  117. */
  118. #define CTK_CONSTRUCTOR_NO_ARG_CPP(PUB) \
  119. PUB::PUB(): d_ptr(new PUB##Private) \
  120. { \
  121. }
  122. /*!
  123. * Define a public class constructor with one argument
  124. *
  125. * Also make sure the Pimpl is initalized
  126. * \see \ref CorePimpl
  127. */
  128. #define CTK_CONSTRUCTOR_1_ARG_CPP(PUB, _ARG1) \
  129. PUB::PUB(_ARG1 _parent) \
  130. : Superclass( _parent ) \
  131. , d_ptr(new PUB##Private) \
  132. { \
  133. }
  134. /*!
  135. * Define the setter in the public class.
  136. *
  137. * This should be put in the .cxx file of the public class. The parameter are
  138. * the name of the public class (PUB), the type of the argument to return (_TYPE),
  139. * the name of the getter(_NAME) and the name of the variable in the Private class(_VARNAME).
  140. * \see \ref CorePimpl
  141. */
  142. #define CTK_SET_CPP(PUB, _TYPE, _NAME, _VARNAME) \
  143. void PUB::_NAME(_TYPE var) \
  144. { \
  145. Q_D(PUB); \
  146. d->_VARNAME = var; \
  147. }
  148. /*!
  149. * Define the setter in the public class.
  150. *
  151. * This should be put in the .cxx file of the public class. The parameter are
  152. * the name of the public class (PUB), the type of the argument to return (_TYPE),
  153. * the name of the setter(_NAME) and the name of the variable in the Private class(_VARNAME).
  154. * \see \ref CorePimpl
  155. */
  156. #define CTK_GET_CPP(PUB, _TYPE, _NAME, _VARNAME) \
  157. _TYPE PUB::_NAME()const \
  158. { \
  159. Q_D(const PUB); \
  160. return d->_VARNAME; \
  161. }
  162. /**@}*/
  163. #endif