Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inner member visibility in class

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?

like image 384
vsoftco Avatar asked Nov 25 '15 03:11

vsoftco


People also ask

What determines the visibility of members in a class?

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.

What visibility modifier should an inner class have?

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.

How do you access members of an inner class?

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.

Can inner class access private?

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.


2 Answers

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.

like image 67
Shafik Yaghmour Avatar answered Oct 06 '22 04:10

Shafik Yaghmour


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.

like image 33
erip Avatar answered Oct 06 '22 05:10

erip