Forward declaration explained below is one of the manifestations of Elaborated Type Specifier.
In some object-oriented languages like C++ and Objective-C, it is
sometimes necessary to forward-declare classes. This is done in
situations when it is necessary to know that the name of the class is
a type, but where it is unnecessary to know the structure.
In C++, classes and structs can be forward-declared like this:
class MyClass;
struct MyStruct;
In C++, classes can be
forward-declared if you only need to use the pointer-to-that-class
type (since all object pointers are the same size, and this is what
the compiler cares about). This is especially useful inside class
definitions, e.g. if a class contains a member that is a pointer (or a
reference) to another class.
Forward-declaration is used to avoid unnecessary coupling which help
reducing compilation time by reducing the number of header inclusion.
This has a triple advantage:
- reduce the number of files opened by
#include
(hence the number of
operating system calls)
- reducing the volume of the pre-processed files
(as the header is not included)
- reducing recompilation impact when the
forward declared class is modified.
Forward declaration of a class is
not sufficient if you need to use the actual class type, for example,
if you have a member whose type is that class directly (not a
pointer), or if you need to use it as a base class, or if you need to
use the methods of the class in a method.
This allows you to use a pointer to the type without having to include the relevant header file in your header file (instead you only need it in the .cpp file).
This helps to reduce dependencies which can improve compile time.
It isn't always needed, particularly with Unreal Engine
core classes as these are often included anyway. However it is good practice to use the prefix if you haven't explicitly included the header file. If you do this, if whatever file was including the header changes to not include it, your code will still compile.
While forward declarations are good, you should avoid ETSs. If you want to forward declare your types, it is best to do so explicitly at file scope:
Bad:
class Bad
{
void Func(class Y* YParam);
class Z* ZProp;
};
Good:
class Y;
class Z;
class Good
{
void Func(Y* YParam);
Z* ZProp;
};
template
andtypename
are not parts of elaborated type specifiers. – Compartmentalize