What Are Forward Declarations in C++

What are forward declarations in C++?

Why forward-declare is necessary in C++

The compiler wants to ensure you haven't made spelling mistakes or passed the wrong number of arguments to the function. So, it insists that it first sees a declaration of 'add' (or any other types, classes, or functions) before it is used.

This really just allows the compiler to do a better job of validating the code and allows it to tidy up loose ends so it can produce a neat-looking object file. If you didn't have to forward declare things, the compiler would produce an object file that would have to contain information about all the possible guesses as to what the function add might be. And the linker would have to contain very clever logic to try and work out which add you actually intended to call, when the add function may live in a different object file the linker is joining with the one that uses add to produce a dll or exe. It's possible that the linker may get the wrong add. Say you wanted to use int add(int a, float b), but accidentally forgot to write it, but the linker found an already existing int add(int a, int b) and thought that was the right one and used that instead. Your code would compile, but wouldn't be doing what you expected.

So, just to keep things explicit and avoid guessing, etc, the compiler insists you declare everything before it is used.

Difference between declaration and definition

As an aside, it's important to know the difference between a declaration and a definition. A declaration just gives enough code to show what something looks like, so for a function, this is the return type, calling convention, method name, arguments, and their types. However, the code for the method isn't required. For a definition, you need the declaration and then also the code for the function too.

How forward-declarations can significantly reduce build times

You can get the declaration of a function into your current .cpp or .h file by #includ'ing the header that already contains a declaration of the function. However, this can slow down your compile, especially if you #include a header into a .h instead of .cpp of your program, as everything that #includes the .h you're writing would end up #include'ing all the headers you wrote #includes for too. Suddenly, the compiler has #included pages and pages of code that it needs to compile even when you only wanted to use one or two functions. To avoid this, you can use a forward-declaration and just type the declaration of the function yourself at the top of the file. If you're only using a few functions, this can really make your compiles quicker compared to always #including the header. For really large projects, the difference could be an hour or more of compile time bought down to a few minutes.

Break cyclic references where two definitions both use each other

Additionally, forward-declarations can help you break cycles. This is where two functions both try to use each other. When this happens (and it is a perfectly valid thing to do), you may #include one header file, but that header file tries to #include the header file you're currently writing... which then #includes the other header, which #includes the one you're writing. You're stuck in a chicken and egg situation with each header file trying to re #include the other. To solve this, you can forward-declare the parts you need in one of the files and leave the #include out of that file.

Eg:

File Car.h

#include "Wheel.h"  // Include Wheel's definition so it can be used in Car.
#include <vector>

class Car
{
std::vector<Wheel> wheels;
};

File Wheel.h

Hmm... the declaration of Car is required here as Wheel has a pointer to a Car, but Car.h can't be included here as it would result in a compiler error. If Car.h was included, that would then try to include Wheel.h which would include Car.h which would include Wheel.h and this would go on forever, so instead the compiler raises an error. The solution is to forward declare Car instead:

class Car;     // forward declaration

class Wheel
{
Car* car;
};

If class Wheel had methods which need to call methods of Car, those methods could be defined in Wheel.cpp and Wheel.cpp is now able to include Car.h without causing a cycle.

What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?

struct forward declarations can be useful when you need to have looping struct declarations. Example:

struct a {
struct b * b_pointer;
int c;
};

struct b {
struct a * a_pointer;
void * d;
};

When struct a is declared it doesn't know the specs of struct b yet, but you can forward reference it.

When you typedef an anonymous struct then the compiler won't allow you to use it's name before the typedef.

This is illegal:

struct a {
b * b_pointer;
int c;
};

typedef struct {
struct a * a_pointer;
void * d;
} b;

// struct b was never declared or defined

This though is legal:

struct a {
struct b * b_pointer;
int c;
};

typedef struct b {
struct a * a_pointer;
void * d;
} b;

// struct b is defined and has an alias type called b

So is this:

typedef struct b b;
// the type b referes to a yet undefined type struct b

struct a {
b * struct_b_pointer;
int c;
};

struct b {
struct a * a_pointer;
void * d;
};

And this (only in C, illegal in C++):

typedef int b;

struct a {
struct b * struct_b_pointer;
b b_integer_type;
int c;
};

struct b {
struct a * a_pointer;
void * d;
};

// struct b and b are two different types all together. Note: this is not allowed in C++

What is the significance of forward declaration in C programming?

Forward declarations of functions in C typically have two different uses.

Modules

The header of exported functions are declared in a header file which is included in a client module.

Mutual Recursion

In mutual recursion two functions call each other repeatedly. Without a forward declaration one of the two functions will be undeclared in the body of the other.

Example:

int Odd(int n);

int Even(int n)
{
return (n == 0)? 1: Odd(n - 1);
}

int Odd(int n)
{
return (n == 0)? 0: Even(n - 1);
}

With a function pointer though, we can do without a forward declaration:

int (*odd)(int n);

int Even(int n)
{
return (n == 0)? 1: odd(n - 1);
}

int Odd(int n)
{
return (n == 0)? 0: Even(n - 1);
}

void Init(void)
{
odd = Odd;
...
}

What is forward declaration in c++? [duplicate]

Chad has given a pretty good dictionary definition. Forward declarations are often used in C++ to deal with circular relationships. For example:

class B; // Forward declaration

class A
{
B* b;
};

class B
{
A* a;
};

Why are forward declarations necessary? [duplicate]

The short answer is that computing power and resources advanced exponentially between the time that C was defined and the time that Java came along 25 years later.

The longer answer...

The maximum size of a compilation unit -- the block of code that a compiler processes in a single chunk -- is going to be limited by the amount of memory that the compiling computer has. In order to process the symbols that you type into machine code, the compiler needs to hold all the symbols in a lookup table and reference them as it comes across them in your code.

When C was created in 1972, computing resources were much more scarce and at a high premium -- the memory required to store a complex program's entire symbolic table at once simply wasn't available in most systems. Fixed storage was also expensive, and extremely slow, so ideas like virtual memory or storing parts of the symbolic table on disk simply wouldn't have allowed compilation in a reasonable timeframe.

The best solution to the problem was to chunk the code into smaller pieces by having a human sort out which portions of the symbol table would be needed in which compilation units ahead of time. Imposing a fairly small task on the programmer of declaring what he would use saved the tremendous effort of having the computer search the entire program for anything the programmer could use.

It also saved the compiler from having to make two passes on every source file: the first one to index all the symbols inside, and the second to parse the references and look them up. When you're dealing with magnetic tape where seek times were measured in seconds and read throughput was measured in bytes per second (not kilobytes or megabytes), that was pretty meaningful.

C++, while created almost 17 years later, was defined as a superset of C, and therefore had to use the same mechanism.

By the time Java rolled around in 1995, average computers had enough memory that holding a symbolic table, even for a complex project, was no longer a substantial burden. And Java wasn't designed to be backwards-compatible with C, so it had no need to adopt a legacy mechanism. C# was similarly unencumbered.

As a result, their designers chose to shift the burden of compartmentalizing symbolic declaration back off the programmer and put it on the computer again, since its cost in proportion to the total effort of compilation was minimal.

What is the difference between forward declaration and forward reference?

From Wikipedia:

Forward Declaration

Declaration of a variable or function which are not defined yet. Their defnition can be seen later on.

Forward Reference

Similar to Forward Declaration but where the variable or function appears first the definition is also in place.

Forward declare entities in C standard library?

Forward declarations of structs are always permissible in C. However, not very many types can be used this way. For example, you can't use a forward declaration for FILE simply because the tag name of the struct is not specified (and theoretically, it may not be a struct at all).

Section 7.1.4 paragraph 2 of n1570 gives you permission to do the same with functions:

Provided that a library function can be declared without reference to any type defined in a
header, it is also permissible to declare the function and use it without including its
associated header.

This used to be rather common. I think the reasoning here is that hard drives are slow, and fewer #include means faster compile times. But this isn't the 1980s any more, and we all have fast CPUs and fast hard drives, so a few #include aren't even noticed.

void *malloc(size_t);
void abort(void);

/* my code here */

Forward Declaration in C

Once you use a forward declaration, the type becomes Incomplete type for the compiler.

Compiler does not know anything about the size or layout of the type and hence you cannot perform any operation which needs the compiler to know these.

In C, If you forward declare a type, you can only use a pointer to that type. Since pointers to all structure types need same size[Note], the compiler is just happy to know that it has a pointer to a type.

If I forward declare a structure and define it other file will it work?

It will as long as you only use a pointer to the structure in the file which forward declares the structure. If you dereference the pointer you will get errors, Since compiler is not aware of the layout of the Incomplete type.


[Note] Thanks to melpomene & Daniel for this clarification.



Related Topics



Leave a reply



Submit