I'm not sure how to order my functions in C++. In C, I simply placed a function that uses another function below that function, as closely as possible - that's pretty common. Like this:
void bar()
{
}
void foo()
{
bar();
}
However, in C++, there are several types of functions:
I'm currently making my function order dependent on how they are ordered in the .hpp file, e.g.:
class Foo_bar {
public:
Foo_bar();
void foo();
private:
int some_member;
void bar();
But now, if the constructor uses foo() or bar(), these will be below the constructor in the source file, inconsistent with my usual ordering. I could of course reorder my header to take account of that:
class Foo_bar {
private:
int some_member;
void bar();
public:
void foo();
Foo_bar();
But I think that's a mess.
Furthermore, in Java, the opposite to my first example seems to be common:
void foo()
{
bar();
}
void bar()
{
}
That's probably due to the top-down thinking common in OOP, in contrast to the bottom-up thinking common in procedural/functional programming. However, with free functions that don't have prototypes, this top-down style is not possible.
Is it even possible to order functions in C++ in a consistent way?
It's possible. You have to use forward declaration.
Declare a function before defining it, and other functions will see it without problem even if they are defined before.
So, you should be able to do this in C++:
void bar(); // forward declaration; note that function bar isn't defined yet
void foo()
{
bar(); // foo knows that bar is declared, so it will search for bar's definition
}
void bar() // here bar is defined, so foo will use this when needed
{
}
It's a pretty good question actually, because readability has a major impact on whoever will read the code after you.
There are 3 kinds of people who will read the code of a class:
For this reason, I try to order the headers so that any user may stop once he got what he was looking for, which means:
class Foo
{
public:
// types
// static methods
// methods (usually constructors,
// then simple accessors,
// then more complicated stuff)
protected:
// same pattern
private:
// same pattern
// attributes
};
// Free functions about this class
// Implementation of inline / template methods
Sometimes I need to declare some types beforehand even though they are private, but this is rare. The goal of this ordering is to absolutely minimize the amount of stuff a reader has to read before he gets what he wants (and stops reading and goes back to what he was doing before having to interrupt himself to look at your code).
Then, regarding "helper" methods, it depends on the type of code:
If some code may require a lot of helpers, I tend to create a dedicated header file in the source directory, giving the following structure:
include/
foo.hpp
src/
fooImpl.hpp --> #include "foo.hpp"
foo.cpp --> #include "fooImpl.hpp"
in order to provide a list of declarations to the reader, because it's easier to browse a list of declarations than to extract the declarations from a list of definitions, whatever the indentation and style.
And of course, always to make it easier, I always order the list of declarations and the list of definitions equally...
You declare the class in a header file, right? And implement most of it in a separate file? If you simply implement the constructor in the implementation file and not in the header, I don't think you'll experience the problem you mentioned (because the entire header will be seen before the constructor is seen to call foo()
or bar()
.
Ordering free functions in C++ obeys the same rules as you mentioned, but like darioo said, you can forward declare them and order the function definitions any way you want. That is also the preferred way: declare everything in header, and put ALL definitions in the source file. This is not possible for templates though, without some non-trivial and non-general anti-template workarounds.
In a class, things are usually different, because there is almost no cases where you fully implement your class in a header, thus the declarations are always read when you're defining the functions in the source file.
I usually order functions in "function", and group eg. getters and setters, constructor/destructor (if possible).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With