| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 | /*=========================================================================  Library:   CTK  Copyright (c) Kitware Inc.  Licensed under the Apache License, Version 2.0 (the "License");  you may not use this file except in compliance with the License.  You may obtain a copy of the License at      http://www.apache.org/licenses/LICENSE-2.0.txt  Unless required by applicable law or agreed to in writing, software  distributed under the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and  limitations under the License.=========================================================================*//**\page CorePimpl CTK Pimpl Macros\brief Utility macros for handling private implementations. It is in addition       to QtGlobal: Q_DECLARE_PRIVATE, Q_DECLARE_PUBLIC,       Q_D and Q_Q.Application code generally doesn't have to be concerned about hiding itsimplementation details, but when writing library code it is important tomaintain a constant interface, both source and binary. Maintaining a constantsource interface is easy enough, but keeping the binary interface constantmeans moving implementation details into a private class. The PIMPL, ord-pointer, idiom is a common method of implementing this separation. ctkPimploffers a convenient way to connect the public and private sides of your class.\section start Getting StartedBefore you declare the public class, you need to make a forward declarationof the private class. The private class must have the same name as the publicclass, followed by the word Private.\subsection pub The Public ClassGenerally, you shouldn't keep any data members in the public class without agood reason. Functions that are part of the public interface should be declaredin the public class, and functions that need to be available to subclasses (forcalling or overriding) should be in the protected section of the public class.To connect the private class to the public class, include theQ_DECLARE_PRIVATE macro in the private section of the public class.Additionally, you must construct the d_ptr pointer in the constructor of the public class.\subsection priv The Private ClassAs mentioned above, data members should usually be kept in the private class.This allows the memory layout of the private class to change without breakingbinary compatibility for the public class. Functions that exist only asimplementation details, or functions that need access to private data members,should be implemented here.To define the private class, nothing special needs to be done, except if youwant the private class to have access to the public class. Then useQ_DECLARE_PUBLIC and create a public class pointer member. The constructor ofthe private class should take a public class reference as a parameter.\section cross Accessing Private MembersUse the Q_D() macros from functions inthe public class to access the private class. Similarly, functions in theprivate class can invoke functions in the public class by using the Q_Q()macro.\section example ExampleHeader file (ctkFooObject.h):\code// Qt includes#include <QObject>// CTK includes#include "ctkCoreExport.h"class ctkFooObjectPrivate;class CTK_CORE_EXPORT ctkFooObject: public QObject{public:  ctkFooObject(QObject* parent = 0);  virtual ~ctkFooObject();  void setProperty(double property);  double property()const;protected:  QScopedPointer<ctkFooObjectPrivate> d_ptr; private:  Q_DECLARE_PRIVATE(ctkFooObject);  Q_DISABLE_COPY(ctkFooObject);};\endcodeImplementation file (ctkFooObject.cpp):\code// CTK includes#include "ctkFooObject.h"class ctkFooObjectPrivate{public:  void processSomething();  double MyProperty;};ctkFooObject::ctkFooObject(QObject* parentObject)  : d_ptr(new ctkFooObjectPrivate){  Q_D(ctkFooObject);  d->MyProperty = 10.;}void ctkFooObject::setProperty(double newProperty){  Q_D(ctkFooObject);  d->MyProperty = newProperty;}double ctkFooObject::property()const{  Q_D(const ctkFooObject);  return d->MyProperty;}\endcode*/#ifndef __ctkPimpl_h#define __ctkPimpl_h// Qt includes#include <QtGlobal>/*! * \ingroup Core * @{ *//*! * Define a public class constructor with no argument * * Also make sure the Pimpl is initalized * \see \ref CorePimpl */#define CTK_CONSTRUCTOR_NO_ARG_CPP(PUB)  \  PUB::PUB(): d_ptr(new PUB##Private)    \    {                                    \    }/*! * Define a public class constructor with one argument * * Also make sure the Pimpl is initalized * \see \ref CorePimpl */#define CTK_CONSTRUCTOR_1_ARG_CPP(PUB, _ARG1)   \  PUB::PUB(_ARG1 _parent)                       \    : Superclass( _parent )                     \    , d_ptr(new PUB##Private)                   \    {                                           \    }    /*! * Define the setter in the public class. * * This should be put in the .cxx file of the public class. The parameter are * the name of the public class (PUB), the type of the argument to return (_TYPE), * the name of the getter(_NAME) and the name of the variable in the Private class(_VARNAME). * \see \ref CorePimpl */#define CTK_SET_CPP(PUB, _TYPE, _NAME, _VARNAME)    \  void PUB::_NAME(_TYPE var)                        \  {                                                 \    Q_D(PUB);                                       \    d->_VARNAME =  var;                             \  }/*! * Define the setter in the public class. * * This should be put in the .cxx file of the public class. The parameter are * the name of the public class (PUB), the type of the argument to return (_TYPE), * the name of the setter(_NAME) and the name of the variable in the Private class(_VARNAME). * \see \ref CorePimpl */#define CTK_GET_CPP(PUB, _TYPE, _NAME, _VARNAME)   \  _TYPE PUB::_NAME()const                          \  {                                                \    Q_D(const PUB);                                \    return d->_VARNAME;                            \  }/**@}*/#endif
 |