0

When I was first learning C++ I noticed that the functions are created from top to bottom unlike in languages such as Java where the order of the function "declarations" in the code does not matter.

C++ example:

#include <iostream>
using namespace std;

int main() {
    test();
    return 0;
}

void test() {

}

But when you swap the order of the functions the program works normally.

Was that intentional when C++ was designed?

sepp2k
  • 363,768
  • 54
  • 674
  • 675
mid
  • 421
  • 5
  • 20
  • 2
    Yes, I think the intention was to speed up compilation. – alain Sep 01 '16 at 15:36
  • You can simply declare the function before using it, you do not have to define it. – SergeyA Sep 01 '16 at 15:37
  • @SergeyA I know that. That's not the problem, though. – mid Sep 01 '16 at 15:38
  • @Midnightas, but what is **the** problem? – SergeyA Sep 01 '16 at 15:39
  • @SergeyA I don't have a problem at all, I was just asking a question because of my curiosity. – mid Sep 01 '16 at 15:39
  • 4
    Declaration preceding usage allows to design single-pass compilers. This is why some languages (among which C/C++) allow forward declarations. –  Sep 01 '16 at 15:43
  • related/dupe: http://stackoverflow.com/questions/2632601/why-are-forward-declarations-necessary – NathanOliver Sep 01 '16 at 15:47
  • 1
    C is an *old* language. It existed back in the day when it really was more important to make things easier on the computer than it was to make things easier on the programmer. –  Sep 01 '16 at 15:55

2 Answers2

4

Neither C or C++ mandates much about the order of function definitions compared to usage.

C allows a function to be declared before usage, but (in C89/90) didn't actually require it. If a call was made to a function that hadn't been declared, the compiler was required to make certain assumptions about the function's type (and the code was invalid if the definition of the function didn't fit those assumptions).

C++ does, however, mandates that free functions at least be declared before usage1. A function definition also declares that function, so tiny programs are often written with definitions preceding usage to avoid having to write declaration separate from their definitions.

For class members, C++ loosens the restrictions somewhat. For example, this is perfectly acceptable:

class Foo { 
    void bar() { baz(); }
    void baz() {}
};

Java differs primarily in simply prohibiting all free functions, so it has only member functions, which follow roughly the same rules as C++ member functions.


  1. Without this, it would be essentially impossible to support some C++ features such as function overloading.
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • The possibility to define `bar` inside the class was only added with C++11 IIRC. – alain Sep 01 '16 at 15:59
  • 2
    @alain: you've been allowed to define functions inside a class definition since C++98 (and well before, for that matter). – Jerry Coffin Sep 01 '16 at 16:01
  • Ah, ok, thanks. (Somehow it seems to be used more often now than earlier, don't know why) – alain Sep 01 '16 at 16:05
1

The problem originates from a series of constrains:

  • value semantics requires that to compile a "call" you need to know parameters and return types sizes.
  • that knowledge must be available to the compiler during compilation of a same translation unit but...
  • knowledge coming from definitions is available only at linking time that is a separate step that happens aside of compilation.

To complicate more, C++ grammar change meaning depending if symbols are variable or types (so, without this knowledge, a<b>c it's even impossible to know what it means: an expression involving three variable or the declaration of a variable of type given by a template instance).

A function definition can reside in another source file and the compiler -when compiling the first one- has no way to access it and hence to know about how wide should be the space to leave on the stack for parameter and return passing.

Your sample -in a wide project- will be code as

//test.h
double test();

__

//test.cpp
#include "test.h" //required to check decl & def consistence
double test()
{ /*...*/ }

__

//main.cpp
#include "test.h" // required to know about test() parameters and return
int main()
{ 
   double z = test();   //how does "=" translate? we need to know what test returns
}

This "project" will be compiled using independent steps:

g++ -c main.cpp //on a program developer machine
g++ -c test.cpp //on a library developer machine
g++ main.o test.o -o yourprogram //on a "package distributor" machine

None of these steps can collect a "global knowledge" about all "global symbols" and their "translation" at the same time. That's why we need headers to broadcast declarations to anyone have to use them

(Note how member functions don't have this problem, being all required to stay into a same class brackets, and as a consequence are granted to fit a same translation unit)

Languages like Java or python don't have this problem, since the modules (not matter how written and loaded) are all loaded-up by a same language-machine instance, that -being unique- can if fact collect all symbols and related types.

language like D (that are like C++ in the sense of "separate compilation") allow order independence between things residing in a same module, but requires module "import" for things coming from other modules, and -in fact- do a two step translation by first collecting symbols and types and then doing call translations.

You can see another description of this problem here

Community
  • 1
  • 1
Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63