Is a class declaration valid after class definition?

I just read this answer and it completely puzzles me.

I always thought that a class declaration could appear many times, and only a definition should exist only once, for example:

/*class Class {*/ class A; // (1) forward declaration class A { // (2) definition, only once int m; }; class A; // (3) declaration again, legal? class A a; // (4) declaration again, legal? /*};*/ 

From a related answer: (3) (and (4)?) Is illegal if the above code is nested inside a class (the definition and class A declarations are nested inside class Class ).

In cppreference, I found the example above, not nested :

 struct s { int a; }; struct s; // does nothing (s already defined in this scope) void g() { struct s; // forward declaration of a new, local struct "s" // this hides global struct s until the end of this block s* p; // pointer to local struct s struct s { char* p; }; // definitions of the local struct s } 

See the second line.

Question: Given that it is illegal inside the class, is this my sample code and the cppreference example above is legal if it is not nested inside the class? Or in a more general sense: when a class declaration can follow a definition (how does this happen in namespaces, for example)? If this is legal, why is there a difference?

+5
source share
2 answers

From [basic.def]:

An advertisement (section 7) may enter one or more names in the translation block or reuse names entered by previous declarations.

From [class.name]:

An declaration consisting solely of a class key identifier; either overriding the name in the current scope or declaring the declaration as the class name. It enters the class name in the current scope.

So this is generally legal for that. The only exception to [class.mem]:

A member must not be declared twice in the member specification, except that the template of a nested class or member class can be declared and then defined later, and except that an enumeration can be entered with an opaque-enumeration-declaration and later updated using an enumeration qualifier.

Perfectly normal in namespace scope, not allowed in class scope.


What is the reason? Well, this rule allows you to "forward" to declare all classes that you need, where you will usually be allowed to:

 // ah struct C; struct A { C* c; }; // bh struct C; struct B { C& c; }; 

without worrying that someone really includes the full declaration and violates everything for you:

 // dh #include "ch" #include "ah" // now C was already declared! #include "bh" // and here too! struct D { ... }; 

This is not so much a problem in class definition. It cannot accurately split multiple files. Thus, the impossibility of overriding nested types actually does not achieve anything.

+8
source

class A; This is a preliminary declaration of incomplete class A (legal).

class A { int m; }; This is the definition of class A (legal).

class A; This is a repeat declaration of class A (legal).

class A a; This is an entity declaration of type a (legal).

+2
source

Source: https://habr.com/ru/post/1232019/


All Articles