Should one use forward declarations instead of includes wherever possible?
No, explicit forward declarations should not be considered as a general guideline. Forward declarations are essentially copy and pasted, or misspelled code, which in case you find a bug in it, need to fixed everywhere the forward declarations are used. This can be error-prone.
To avoid mismatches between the "forward" declarations and its definitions, put declarations in a header file and include that header file in both the defining and the declaration-using source files.
In this special case, however, where only an opaque class is forward declared, this forward declaration may be okay to use, but in general, to "use forward declarations instead of includes whenever possible", like the title of this thread says, can be quite risky.
Here are some examples of "invisible risks" concerning forward declarations (invisible risks = declaration mismatches that are not detected by the compiler or linker):
Explicit forward declarations of symbols representing data may be unsafe, because such forward declarations might require correct knowledge of the footprint (size) of the data type.
Explicit forward declarations of symbols representing functions may also be unsafe, like the parameter types and the number of parameters.
The example below illustrates this, e.g., two dangerous forward declarations of data as well as of a function:
File a.c:
#include <iostream>
char data[128][1024];
extern "C" void function(short truncated, const char* forgotten) {
std::cout << "truncated=" << std::hex << truncated
<< ", forgotten=\"" << forgotten << "\"\n";
}
File b.c:
#include <iostream>
extern char data[1280][1024]; // 1st dimension one decade too large
extern "C" void function(int tooLarge); // Wrong 1st type, omitted 2nd param
int main() {
function(0x1234abcd); // In worst case: - No crash!
std::cout << "accessing data[1270][1023]\n";
return (int) data[1270][1023]; // In best case: - Boom !!!!
}
Compiling the program with g++ 4.7.1:
> g++ -Wall -pedantic -ansi a.c b.c
Note: Invisible danger, since g++ gives no compiler or linker errors/warnings
Note: Omitting extern "C"
leads to a linking error for function()
due to the c++ name mangling.
Running the program:
> ./a.out
truncated=abcd, forgotten="♀♥♂☺☻"
accessing data[1270][1023]
Segmentation fault
delete
a pointer using only a forward declaration, but if the class in fact has a non-trivial destructor then you get UB. So ifdelete
"only uses pointers" then yes, there's a reason. If it doesn't count, not so much. – Sideman