2015-11-25 10 views
11

nach dem Standard C++,innere Element Sichtbarkeit in der Klasse

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 sollte der folgende Code kompilieren, und in der Tat hat es

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

Allerdings, wenn ich Kommentar- die Zeile, die die Elementfunktion void Foo::f(Bar) definiert, dann kann der Code nicht mit dem Fehler

kompiliert werden

error: 'Bar' has not been declared

Beim erneuten Lesen des Standards scheint es tatsächlich so zu sein, dass Funktionsparameter nicht als Orte betrachtet werden, an denen die Klasse als abgeschlossen betrachtet wird. Es macht jedoch überhaupt keinen Sinn. Können Sie etwas Licht, warum kann ich nicht Bar in einem Funktionsparameter verwenden (aber ansonsten kann es innerhalb eine Funktion ohne irgendwelche Probleme überhaupt) vor seiner vollständigen Definition verwenden?

+0

Meine Die beste Vermutung ist, dass die Funktion selbst erst dann "evaluiert" wird, wenn "struct Foo" vollständig ist und somit "Bar" verfügbar ist. Bei der Funktionsdeklaration muss der Typ bekannt sein, um die Funktionssignatur erzeugen zu können. Sie erhalten das gleiche Problem beim Definieren eines typedef, nachdem Sie versuchen, den Typ in einer Funktionsdeklaration zu verwenden. – RedX

+0

Bei dieser Frage geht es eher um die Namenssuche als um die Vollständigkeit des Klassentyps. –

+0

@RedX und T.C., ich sehe jetzt, ich glaube, du hast Recht. Wenn Sie eine Antwort schreiben können, nehme ich sie gerne an. – vsoftco

Antwort

6

In allen in 9.2[class.mem] aufgelisteten Fällen kann der Typ zurückgestellt werden, bis die Klasse vollständig definiert ist. Wir können diese Gründe in defect report 643: Use of decltype in a class member-specification aufgeführt, die sagt:

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.

Als T. C. weist darauf hin, gibt es auch Probleme der Nachschlagen beteiligt wie defect report 325: When are default arguments parsed? und defect report 1352 befassen sich mit. Je später man erwähnt auch die gleiche Technik in der Lage, das Parsen aufzuschieben, bis die Klasse abgeschlossen ist:

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.

2

Vom 03-Standard 3.4.1/8 (Uneingeschränkt-Namen-Suche):

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.

Verwandte Themen