C ++ nested class in split header file

I would like to move the nested Inner class from Outer.h to a separate header file:

class Outer{ class Inner{ public: Inner(Outer& o){} }; public: Outer():i(*this){} ~Outer(){} Inner i; }; 

And for 'main.cpp'

 #include "Outer.h" int main(){ Outer o; return 0; } 

But as soon as I try to put the inner class inside the split header like this:

 class Outer{ class Inner; public: Outer():i(*this){} ~Outer(){}; Inner i; }; 

and put the inner class in "Inner.h" as follows:

 class Outer::Inner{ public: Inner(Outer& o){} }; 

and add in the main #include 'Inner.h' like this:

 #include "Outer.h" #include "Inner.h" int main(){ Outer o; return 0; } 

I get the following error from the compiler: Outer.h: 10: 9: error: field "i" is of an incomplete type.

I understand more or less why, but I cannot find a problem to achieve what I want to do.

+7
c ++ nested
source share
2 answers

To create an Outer object, the layout of the class memory must be known, in which case it is not (precisely because of Inner incompleteness).

The way to do this is to use a pointer, then the declaration will work forward (since the pointer has a fixed size, and then the Outer memory layout will be allocated).


What I mean:

 // header file class Outer{ class Inner; public: Outer(); ~Outer(); Inner* i; }; 

And then, in the source file for the Outer class, define

 // include header file for Outer and Inner classes // source file Outer::Outer() { i = new Inner( *this ); }; Outer::~Outer() { delete i; }; 

You need to do this in the source file because you need to include header file of the Inner class (you cannot include it directly in the header file because you will encounter a circular dependency (the two header files will include each other) since the header file Inner must also have an Outer header file).


This is also known as pImpl idiom - an "implementation pointer", and often Inner is called Impl and a member of pImpl or something like that, depending on the encoding convention used. The idea is to hide any implementation details, such as private / protected members (functions, data).

+5
source share

If you don't want to turn your i member into a pointer, the best option is to move the Inner definition outside of Outer and use namespaces for nesting.

Please note that in this case you will need to include the Inner.h header before Outer .

+1
source share

All Articles