According to the C++ standard,
9.2 [class.mem]:
A class is considered a completely-defined object type (3.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, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification
So, the code below should compile, and indeed it does
struct Foo{
Foo()
{
Bar bar; // Bar is fully visible here, even though it's defined later
}
//void f(Bar){} // But NOT VISIBLE if used as a function parameter
struct Bar{};
};
int main()
{
Foo foo;
}
Live on Coliru
However, if I uncomment the line that defines the member function void Foo::f(Bar)
, then the code fails to compile with the error
error: 'Bar' has not been declared
Reading again the standard it indeed seems that function parameters are not considered as places where the class is regarded as complete. However, it does not make any sense at all. Can you shed some light why I cannot use Bar
in a function parameter (but otherwise can fully use it inside a function without any issues whatsoever) before its full definition?
Visibility is based on the scoping rules of C++. A class member can be visible and inaccessible at the same time. Static members as an example are visible globally through out the running of your application but accessible only with regard to the modifier applied to them.
We can use all of the standard visibility modifiers on inner classes, so a static inner class could be private, protected, default, or publicly visible.
As the inner class exists inside the outer class we must instantiate the outer class in order to instantiate the inner class. Hence, to access the inner class, first create an object of the outer class after that create an object of the inner class.
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
In all the cases listed in 9.2
[class.mem] knowing the type can be deferred until the class is fully defined. We can see this rationale listed in defect report 643: Use of decltype in a class member-specification which says:
In the other cases where a class type is considered complete within the definition of the class, it is possible to defer handling the construct until the end of the definition. That is not possible for types, as the type may be needed immediately in subsequent declarations.
As T.C. points out there is also issues of lookup involved as defect report 325: When are default arguments parsed? and defect report 1352 deal with. The later one also mentions the same technique of being able to defer parsing till the class is complete:
The rules regarding class scope and when the class is considered to be complete (normally implemented by deferred parsing of portions of class member declarations) are inconsistent and need to be clarified.
From the 03 standard, 3.4.1/8 (Unqualified name lookup):
A name used in the definition of a member function (9.3) of class X following the function’s declarator-id29) shall be declared in one of the following ways:
— before its use in the block in which it is used or in an enclosing block (6.3), or
— shall be a member of class X or be a member of a base class of X (10.2), or
— if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies in turn to Y’s enclosing classes, starting with the innermost enclosing class),30) or
— if X is a local class (9.8) or is a nested class of a local class, before the definition of class X in a block enclosing the definition of class X, or
— if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within a local class of a function that is a member of N, before the member function definition, in namespace N or in one of N’s enclosing namespaces.
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