2

In C++ ,most of developers are using pimpl idiom or opaque pointers to hide the private data/implementation from the public API, for an example :

  1. => first case ## Opaque Pointer and PIMPL idiom ##

// in header file

class Node; 
class Graph {  
 public:    
  A();  
 private:  
  Node* m_nodeImpl; 
}

// class Node will be defined in respective cpp

2. => second case ## Inner class / Nested class approach ##

// in header file

class Graph {  
 public:    
  Graph(){};  
 private:  
  class Node
  {
    // implementation goes here
  }
  Node* m_nodeImpl;
}

Question is ...

  1. What is the actual difference between these two approached in perspective of class design (design patterns may be)?
  2. What are the advantages and disadvantages on each over each?
Buddhika Chaturanga
  • 957
  • 2
  • 14
  • 29
  • 1
    You can combine the two, where you just *declare* the `Graph::Node` class, and have the definition in the source file. – Some programmer dude Aug 01 '19 at 10:10
  • As for differences, in the second example human readers of the header file can see the details of the `Node` class. – Some programmer dude Aug 01 '19 at 10:12
  • @Someprogrammerdude I think that's the major advantage of pimpl/opaque_ptr over the nested class impl right? (to hide even the details) – Buddhika Chaturanga Aug 01 '19 at 10:15
  • 2
    Usually this is not issue of "hiding" from human, but rather dependency problems. I.e. if implementation (and declaration) of `Node` depends from some other class(es) you need to include it in your header. In PIML case you don't need this. And this can be important for example for API classes that don't need to expose implementation details. – sklott Aug 01 '19 at 10:18
  • @sklott yeah I forgot about that, thanks for bringing it to my attention again, yeah, therefore considering both factors ,pimpl preferred right?then when to use inner classes in C++ actually? except human readable thingy – Buddhika Chaturanga Aug 01 '19 at 10:20

1 Answers1

2

You're mixing up several things:

  1. first example

    1. Type: opaque - that means the type name is visible to users of this header, but the definition is hidden.

      Opaque types are particularly useful when you want to share a pointer with your users, but not the details of what it points to (either to discourage users from fiddling with it, or to break up dependencies).

    2. Storage: pimpl. This just means the users know you (may) have an instance of the opaque type somewhere, and they know the size of your top-level object includes that pointer.

  2. second example

    1. Type: nested - this avoids polluting the enclosing namespace (so there can be other types of Node in the same namespace in your program, unlike the first example) but exposes all the details.

      Note that your nested type could also be forward-declared, to control both visibility and namespace pollution.

    2. Storage: missing. Did you mean to have a Node *m_impl here too? Otherwise the examples aren't directly comparable, as there's nowhere for your Graph to keep a Node, however the type is declared.

Useless
  • 64,155
  • 6
  • 88
  • 132