Вопрос

I came across an implementation which had the pimpl class as a header and included that in the pimpl implementation. Does it even make sense? Something like this:

UI.h

class UI {

public:

   UI();
   virtual ~UI();

   // bunch of methods
private:

      UIImpl* m_impl;
}

UIImpl.h

class UIImpl
{

public:

  UIImpl( ...) ;
  ......
}

UIImpl.cpp

#include "UIImpl.h" 

UIImpl::UIImpl()

{

  //Actual Implementation
  ...

}

I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?

Это было полезно?

Решение

They're different kinds of header. UI.h is "public" - it's part of the external interface of the library, for use by its clients.

UIImpl.h is "private," just as the UIImpl.cpp is. As long as it's never included in a public header, it can remain invisible to clients, just as the .cpp itself can.

There can be several reasons for splitting the impl class definition into a header file. Perhaps some other implementation classes are passed UIImpl& parameters. Perhaps it's easier to run doxygen on headers only. Perhaps it's just project policy.

The bottom line is, it's still Pimpl, as long as you don't publish the private header.

Другие советы

It makes perfect sense to do this. It allows the UIImpl.h (and related .cpp) to be modified, without having to change code that is dependent on UI.h. Since the UIimpl class is just stored as a pointer [and presumably the UI itself only has access to public methods of the UIimpl class, nothing about the UIimpl class is known to the UI.h code.

In fact, you probably NEED the "UIimpl.h" to allow the public functionality of the class to be seen by the UI class.

E.g.

class UIImpl
{

public:

     UIImpl( ...) ;
     void func() { ... }
}

class UI 
{

  public:

   UI();
   virtual ~UI();

   // bunch of methods
   void func() { m_impl->func(); }
   ... 
}

For this to work, UI needs to know the public interface provided by the UIimpl class.

I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?

Not necessarily. pIMPL can be used for fast value swapping (probably in architectures before C++11/move semantics), bridge design pattern or any other number of other reasons.

An example of bridge design pattern:

class WinImpl { virtual ~WinImpl() = 0; /* other interfaces here */ };

// different header file(s)
#ifdef WIN32
class WindowsWinImpl: public WinImpl { /* ... */ };
#else
class LinuxWinImpl: public WinImpl { /* ... */ };
#endif

// different header file
class Window { private: WinImpl* pImpl /*= OSWindowFactory::CreateImpl();*/ };

In this case you have a pImpl model, where it is perfectly OK to include the definition of WinImpl in the header of Window class (because the purpose is not to hide the implementation but to abstract it's interface).

Yes, it does make sense.

An example of use: in code developed for more than one operating system, UI.h would be visible from the operating-system-independent code, but not UIImpl.h. The operating-system-dependent-code (implementation code) would see both headers, UI.h and UIImpl.h

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top