The correct terminology is "incomplete type". A class type is
known as soon as it is declared, i.e. immediately after the name
of the class in either a declaration or a definition. The class
type is only complete after the final closing } of the
definition.
. It's not necessary to have the full declaration of
Yes and no. I think that Rahul's problem was more along the
lines of:
class Foo
{
Foo& myFoo ;
} ;
According to the standard, myFoo, here, is a definition (not a
declaration), so one would expect it to be initialized with an
object. Which isn't possible at this point in the program,
because the type Foo is still incomplete, and you cannot have
objects with incomplete types.
The reason, of course, is that the definition of myFoo is
actually a definition of an unspecified number of instances of
the reference; each instance only comes into being when the
constructor of Foo is called. At that point, Foo must be
complete (and the reference must have an initializer, in the
initialization list), or the code is ill formed. (Note that if
the definition of the constructor is given within the class
body, it is processed as if it were immediately following the
complete definition of the class, so even something like the
following is legal:
class Foo
{
public:
Foo() : myFoo( *this ) { }
Foo( Foo& parent ) : myFoo( parent ) {}
Foo& myFoo ;
}
(Note that if the class contains a reference to itself, the only
possible initialization for the first instance is to itself.
Class instances are created one after the other, there are no
null references, and the reference must refer to an "existing"
object.)
Then how does a static member object work? The type is
incomplete even for that isn't it?
A declaration of a non-static data member in a class is a
definition, and requires a complete type. A declaration of a
static data member is not a definition, and so does not require
a complete type (although if the static data member is used, you
must provide a definition somewhere, and the type must be
complete when you provide that definition).
Note the different lifetimes (and storage durations) associated
with static and non-static members. A non-static member has the
same lifetime and storage duration as the containing instance,
and is only initialized (and only requires a complete type) when
the containing instance is initialized. A static member has
static lifetime and storage duration, and is initialized during
static initialization, very much as if it were a variable
declared at namespace scope.