Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward declaration of nested types/classes in C++

People also ask

Can you forward declare a nested class?

You cannot forward declare a nested structure outside the container. You can only forward declare it within the container.

What is the forward declaration of classes?

Forward Declaration refers to the beforehand declaration of the syntax or signature of an identifier, variable, function, class, etc. prior to its usage (done later in the program). In C++, Forward declarations are usually used for Classes.

What is forward declaration in Objective C?

In Objective-C, classes and protocols can be forward-declared like this: @class MyClass; @protocol MyProtocol; In Objective-C, classes and protocols can be forward-declared if you only need to use them as part of an object pointer type, e.g. MyClass * or id<MyProtocol>.

What is forward declaration error in C?

This is because a definition of a struct is not an implementation. C compiler needs this information in order to process declarations of the struct correctly. A forward declaration lets you define a pointer to your struct ; declaring a struct itself requires a full definition.


You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.


class IDontControl
{
    class Nested
    {
        Nested(int i);
    };
};

I needed a forward reference like:

class IDontControl::Nested; // But this doesn't work.

My workaround was:

class IDontControl_Nested; // Forward reference to distinct name.

Later when I could use the full definition:

#include <idontcontrol.h>

// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
    // Needed to make a forwarding constructor here
    IDontControl_Nested(int i) : Nested(i) { }
};

This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.

But in my very simple case, it seems to work.


If you really want to avoid #including the nasty header file in your header file, you could do this:

hpp file:

class MyClass
{
public:
    template<typename ThrowAway>
    void doesStuff();
};

cpp file

#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"

template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
    // ...
}

But then:

  1. you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
  2. your function can not be virtual (because it is a template)

So, yeah, tradeoffs...


I would not call this an answer, but nonetheless an interesting find: If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least). When the class definition of C is found, it seems to silently overwrite the namspace C.

namespace C {
    typedef struct {} D;
}

class A
{
public:
 typedef struct/class {...} B;
...
C::D *someField;
}

class C
{
public:
   typedef struct/class {...} D;
...
   A::B *someField;
}

If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:

class CD {

};

class C {
public:

    using D = CD;

};

class CD;