2013-01-01 13 views
7

Mein Verständnis war, dass eine friend Erklärung auch als Forward-Deklaration für eine Klasse dienen könnte, wenn die class Spezifizierer verwendet wurden, wie in diesem Beispiel:Freund Erklärung nicht vorwärts erklärt

class A 
{ 
    friend class B; 
    B* b; 
}; 

class B {}; 

int main() {} 

jedoch g ++ (4.6. 3 und 4.7.0) geben mir die folgenden Fehler (g ++ - 4.7 Unterstützung für extended friend declarations haben soll), die ohne eine Vorwärtsdeklaration erwartet wird:

main.cpp:6:2: error: ‘B’ does not name a type

In einem Versuch, meine Erwartungen zu bestätigen, dass die friend class B; sollte als eine Vorwärtsdeklaration dienen, fand ich this answer und this answer, aber keine war schlüssig (oder ich konnte nicht viel von ihnen zumindest schließen), so versuchte ich, den C++ 11 Standard zu konsultieren und fand dieses Beispiel:

class X2 { 
    friend Ct; // OK: class C is a friend 
    friend D; // error: no type-name D in scope 
    friend class D; // OK: elaborated-type-specifier declares new class 
} 

Aufgrund meiner Lektüre der dritten Erklärung sollte mein friend class B sein ein -Typ-Spezifizierer erarbeitet eine neue Klasse zu deklarieren.

Ich beginne gerade zu verstehen, offiziellen Standard Wortlaut, so dass ich etwas verpassen muss. Was verstehe ich falsch?

Antwort

5

Ihre friend class B; Erklärung tut als Vorwärts Erklärung dienen, aber eine solche Erklärung nicht durch Namenssuche, bis eine passende Erklärung vorgesehen ist, gefunden.

[class.friend]/11:

If a friend declaration appears in a local class (9.8) and the name specified is an unqualified name, a prior declaration is looked up without considering scopes that are outside the innermost enclosing non-class scope. For a friend function declaration, if there is no prior declaration, the program is ill-formed. For a friend class declaration, if there is no prior declaration, the class that is specified belongs to the innermost enclosing non-class scope, but if it is subsequently referenced, its name is not found by name lookup until a matching declaration is provided in the innermost enclosing nonclass scope.

+0

Nein, es ist wirklich ':: B': http : //ideone.com/bEgZrq. Beachten Sie "das innerste einschließende * non-class * scope". – aschepler

+0

@ K-ballo Also wenn es heißt, eine neue Klasse deklariert, ist das nur für die Zwecke der Freundschaftsdeklaration, aber nicht für etwas anderes? – JaredC

+0

@ JaredC: Das klingt ungefähr richtig für mich ... –

6

Werfen Sie einen Blick auf 11.3 Ziffer 11:

For a friend class declaration, if there is no prior declaration, the class that is specified belongs to the innermost enclosing non-class scope, but if it is subsequently referenced, its name is not found by name lookup until a matching declaration is provided in the innermost enclosing nonclass scope.

Example:

class X; 
void a(); 
void f() { 
    class Y; 
    extern void b(); 
    class A { 
    friend class X; // OK, but X is a local class, not ::X 
    friend class Y; // OK 
    friend class Z; // OK, introduces local class Z. 
    friend void a(); // error, ::a is not considered 
    friend void b(); // OK 
    friend void c(); // error 
    }; 
    X *px;   // OK, but ::X is found 
    Z *pz;   // error, no Z is found 
} 
Verwandte Themen