This is a multi-part message in MIME format. --------------010203020901030206030903 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hello, I've read this in the TODO file of kdelibs: - Change all FooPrivate *d; -> Private * const d; and place initialization in the constructor (for classes that would benefit from this). To help catch silly mistakes since d should never change. Also consider changing to use KStaticDeleter to help prevent mistakes where developers forget to delete the pointer. Maybe make use of Qt4 helper macros? (Frerich) The problem with such a solution is: - you can forget to create the private class - you can forget to delete d - using a pure pointer for the pimpl violates const correctness. It is possible to call non const member functions of the implementation object Attached a proposal for a different implementation of the Pimpl idiom, which has not above problems. It automatically creates on construction, and deletes on destruction the private implementation object, it also propagates the constness to the private object. It is pure C++ and needs no macros or static variables. Cheers, Peter See also: http://www.gotw.ca/publications/mill04.htm http://www.gotw.ca/publications/mill05.htm http://boost-consulting.com/vault/ --------------010203020901030206030903 Content-Type: text/plain; name="Makefile" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Makefile" BIN = main CXXFLAGS = -Wall -Wold-style-cast -Wundef -Wsign-compare -Wconversion -Wpointer-arith -pedantic -O2 CPPFLAGS = -I. -DNDEBUG .PHONY: build clean build: $(BIN) clean: rm -f $(BIN) $(BIN).exe $(BIN).o --------------010203020901030206030903 Content-Type: text/plain; name="main.cpp" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="main.cpp" #include #include ///////////////////////////////////////// // Definition of ImplT ///////////////////////////////////////// template<> struct KImplDef { KImplDef() { std::cout << "A created\n"; } ~KImplDef(){ std::cout << "A destroyed\n"; } void foo() { std::cout << "Impl::foo() \n"; } void foo() const { std::cout << "Impl::foo() const \n"; } }; ///////////////////////////////////////// // class A definition ///////////////////////////////////////// A::A() {} void A::foo(){ d->foo(); } void A::foo() const { d->foo(); } ///////////////////////////////////////// // main ///////////////////////////////////////// int main() { A* a = new A; const A* ca = new A; a->foo(); ca->foo(); delete a; delete ca; return 0; } --------------010203020901030206030903 Content-Type: text/plain; name="KImpl.h" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="KImpl.h" #ifndef KPIMPL_H #define KPIMPL_H #include ///////////////////// // KImpl ///////////////////// template < class T, typename Pointer = std::auto_ptr > class KPimpl { public: typedef T Impl; KPimpl() : ptr_(new T) {} T* operator->() { return ptr_.operator->(); } T& operator*() { return ptr_.operator*(); } const T* operator->() const { return ptr_.operator->(); } const T& operator*() const { return ptr_.operator*(); } Pointer& wrapped() { return ptr_; } const Pointer& wrapped() const { return ptr_; } private: KPimpl(const KPimpl&); KPimpl& operator=(const KPimpl&); Pointer ptr_; }; ////////////////////////////////////////// // template for the implementations ////////////////////////////////////////// template struct KImplDef; template class SmartPtr = std::auto_ptr > struct KImpl { typedef KPimpl < KImplDef, SmartPtr< KImplDef > > Ptr; }; #endif --------------010203020901030206030903 Content-Type: text/plain; name="type.h" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="type.h" #include ///////////////////////////////////////// // class A declaration ///////////////////////////////////////// class A { public: A(); void foo(); void foo() const; private: KImpl::Ptr d; }; --------------010203020901030206030903--