In Thinking in C++ by Bruce eckel, there is an example given regarding friend functions as
// Declaration (incomplete type specification):
struct X;
struct Y {
void f(X*);
};
struct X { // Definition
private:
int i;
public:
friend void Y::f(X*); // Struct member friend
};
void Y::f(X* x) {
x->i = 47;
}
Now he explained this:
Notice that Y::f(X*) takes the address of an X object. This is critical because the compiler always knows how to pass an address, which is of a fixed size regardless of the object being passed, even if it doesn’t have full information about the size of the type. If you try to pass the whole object, however, the compiler must see the entire structure definition of X, to know the size and how to pass it, before it allows you to declare a function such as Y::g(X).
But when I tried
void f(X);
as declaration in struct Y, it shows no error. Please explain why?
The parameter types for function declarations may be incomplete.
For data member declarations and all definitions however, the type has to be complete:
struct A;
struct B {
void f(A); // declaration, fine
void g(A) {} // error
A a; // error
};