Example:
class A
{
class B
{
A c;//error!A is an incomplete type
void test() { A b;/*OK,but why?*/ }
};
};
The code snippet seems strange for me,what's the difference between the two usage of A
?
As seen in the compile error:
prog.cpp:8:7: error: field ‘c’ has incomplete type ‘A’
A c;//error!A is an incomplete type
^
prog.cpp:4:8: note: forward declaration of ‘class A’
class A
^
Class A
is a forward-declaration which:
Declares a class type which will be defined later in this scope. Until the definition appears, this class name has incomplete type. This allows classes that refer to each other:
For class A
is not "fully" defined until class B
is.
Thus, class A
is a forward-declaration and an incomplete type.
However, for
void test() { A b;/*OK,but why?*/ }
If forward declaration appears in local scope, it hides previously declared class, variable, function, and all other declarations of the same name that may appear in enclosing scopes:
Thus, it is fine to have A
declared in local scope.
[class.mem]/6 specifies that:
A class is considered a completely-defined object type (6.9) (or complete type) at the closing
}
of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
The definition of an object (as in A b;
or A c;
) requires the object to have a complete type. As the paragraph above states, the class type is incomplete within its own definition, except in certain places: namely, inside member function bodies and a few other places.
This rule makes it possible to write nontrivial code inside member functions defined inline while also prohibiting a class from containing itself (directly or indirectly).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With