views:

142

answers:

3

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?

A: 

The problems is when you change the declaration in struct X.

So, inside struct X you tell the compiler the struct has a function which receives something of type X, but wait a minute, type X is not fully define at this point!

You can't use an incomplete type as a parameter for function f but you can use the address of an incomplete type, thus X*.

On a site note, it will be very important for you to increase your acceptance rate so you get answers for your future questions and important for my ego if i got the right answer :)

mcabral
Yes, that I understand that we can't use an incomplete type as parameter for function but when I declare function in struct Y asvoid f(X);and in struct X, I writefriend void Y::f(X);then there is no error.How it is allowed?
Happy Mittal
+1  A: 

It should be fine to pass the incomplete object X by value, though during the function implementation the complete type X must be available irrespective of whether the object of type X is actually used in function or not. A function declaration is all fine with incomplete object as argument or return type, except covariant return type (for member function) where such return type must be complete type.

abir
Thanks, but the last line of his explanation suggests that we can't even declare as void f(X);
Happy Mittal
Only during the function definition, the compiler need to know size of object of type X, when X is passed by value, so that it can set up local stack irrespective of whether such value is in use or not. While for a reference or pointer type size of pointer/reference is known to compiler, and hence there is no problem implementing such function as long as any member of the object x is not accessed. If one need to access members of x, complete type of X need to be available. Probably the book wanted to say that as X is incomplete type,in place implementation of f(X*) as given is not possible.
abir
+1  A: 

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
};
Georg Fritzsche