Why don't methods defined in classes in C++ need forward declarations when referring to methods that only show up later in the class?

Viewed 147

Why is this a compilation error:

void f() {
    g();
}

void g() {

}

but not this:

class X {
    void a() {
        b();
    }

    void b() {
        
    }
};

I was under the assumption the compiler would (at least, generally) read code from top-down, left-to-right, and that was the reason that in the 1st piece of code we'd need to define a void g() forward declaration before f() to make the code compile. But that logic doesn't seem to apply to classes -- why?

2 Answers

C dates from 1972; C++ dates from 1985. C++ inherited the forward declaration requirement and the design of header files from C, and kept that behavior for compatibility, but was able to improve things for classes, with C didn't have.

Since all members of a class must be declared within it, it is assumed by the language that a class has one authorship (which might comprise many individual authors). As such, it is reasonable to provide the convenience of forward lookup where technically feasible.

This also obviates the need for forward declarations of member functions and data members, which are accordingly disallowed.

The same argument does not apply to the open set of non-member functions, especially in the global namespace; it would be problematic for lookup to consider functions introduced by unrelated components later in the translation unit, especially if a declaration is available before the use but a later one might override it due to namespace search order or a better parameter match. That might outdate the return type of a function declared with auto after it had been used, for instance. It could also make it unclear even outside a template whether a name referred to a type or template, bringing in all the complexity of the typename and template parser guides.

Related