Is it possible to use functions in an arbitrary order in C++?

Asked

Viewed 81 times

3

Apparently, the order in which functions are written matters in C++. Example, this code compiles:

#include <iostream>

using namespace std;

int add_number(int x, int y){
    return x+y;
}

int main(){
    int a{10};
    int b{43};
    cout<<add_number(a,b) <<endl;
}

But this code does not compile:

#include <iostream>

using namespace std;

int main(){
    int a{10};
    int b{43};
    cout<<add_number(a,b) <<endl;
}

int add_number(int x, int y){
    return x+y;
}

I found this unexpected because in Rust, the other compiled language I know, the order in which the functions are written doesn’t matter. Example:

fn add_numbers(x:i32, y:i32)->i32{
    return x+y
}

fn main() {
    let a:i32 =10;
    let b:i32 =43;
    println!("{}",add_numbers(a,b))
}

If you invert the order of the functions, the result does not change.

Is it possible to do the same in C++? In other words, it is possible to access functions regardless of the order in which they were written?

What explains this difference in behavior between C++ and Rust?

3 answers

5


C and C++ are languages that have chosen to be one step, that is, they analyze what they find in the order and evaluate what to do with that in the order that came.

Modern languages tend to avoid this limitation, although compilation performance suffers somewhat.

In the past that gain was very important today is not more. But it is possible that some codes use this feature and a change could break the compatibility of C and C++.

The most modern languages work with two-step compilation (not to be confused with phases). Then there is a reading and "interpretation" of some points of the code and only then other points are evaluated. In general what is of the highest level such as the declaration of global types, structures and information, as are the functions, is that they are evaluated in the first step, then the compiler has a table of symbols and additional information of how they are composed to use in the second step. This way the order as each thing was declared doesn’t matter. This gives more flexibility by charging the price of performance.

I told you about PHP.

Note that the compiler only needs to know the job signature to see if your code is calling in accordance with what has been declared, just need to check the contract, do not need the function set before because this is implementation details, including the code of the function might not even be in that file or even compilation unit, could come from a static or dynamic library, as it is in other languages.

More modern languages often have metadata files with signatures when the source is not available (or they read the entire source, typical case of interpreted languages, which is much worse).

In C and C++ you need the sources at least of the function signatures and the structures and other global information that can be made available externally. Again modernity brought something that these languages could not have at the time. This is solved with so-called headers.

C++ could have changed that but lost some compatibility with C. But now they don’t care that much and found a way to have some modernity without breaking compatibility.

One can work with modules in C++20 forward. They are implemented in the same modern way that Rust and other languages use and the statements do not need to be present before use, as long as they exist and are present in a module, which is something new in the language, and of course, that it has been imported. Modules are much more than this. Documentation. Proposal. Presentation.

When I was researching I found Why, in C, a function needs to be declared before it is used?, maybe a duplicate, except for the last paragraph I answered here.

3

Actually this is more of a feature of language.

In C++ (as in C), you must have the function declared before using it. Note, in your first example, that the function add_number was declared (and implemented) before to be called. Therefore, there are no mistakes.

In the second example, the function add_number, to be invoked in main, had not yet been declared or implemented.

As pointed out to another answer, it is still possible to declare a function and then implement it. This happens, for example, in header files, which are included at the beginning of the archive. In fact, that is also why this type of inclusion comes at the beginning of the archive, that is, to ensure that all external functions are properly declared before use.

Therefore, the answer to the question is no. You cannot use a function in arbitrary order, so the statement is mandatory before use.


That kind of "concern" is not necessary in Rust. This is because the Rust compiler parses all statements of a file before checking the body of functions, so that the declaration order becomes irrelevant.

2

In C it is only possible to use a member that has already been declared, it would be a similar mistake to do so:

x = 10;
int x;

Hence, the compiler when finding a member (variable, Function, Structure, etc.) validates whether it has already been declared, so if it is used in main, must be declared before.

Anyway, as well as the variables, it is possible to declare the functions, and implement them next, then the code will work if so for example:

// aqui só declarou a function, indicando ao compilador que existe
int add_number(int x, int y);

int main(){
    int a{10};
    int b{43};
    cout<<add_number(a,b) <<endl;
}


// aqui implementou. A implementação pode ficar no final, pq só será utilizada em runtime
int add_number(int x, int y){
    return x+y;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.