Learncpp: 01 Functions and Files
Function Return Values
- The
main()
function must return anint
. - Explicit function calls to
main()
should be avoided. - Most compilers detect missing return values, but in complex cases, they might fail to do so.
- Nested functions are not allowed in C++.
Function Parameters and Arguments
- A parameter is a variable in a function’s header. It behaves like a regular variable but is initialized with a value provided by the caller.
- An argument is the actual value passed to a function when calling it.
- When a function is called:
- Parameters are created as variables.
- Argument values are copied into parameters (pass by value).
- These parameters are called value parameters.
- Unreferenced parameters exist but are not used in the function body.
- Unnamed parameters are parameters without a name.
Local Scope
- Local variables are declared inside a function and only accessible within that function.
- Creation & Destruction:
- Created when execution reaches their definition.
- Destroyed when they go out of scope (end of
{}
block).
- Scope & Lifetime:
- Scope defines where a variable is accessible.
- Lifetime lasts from creation to destruction.
- Temporary objects (e.g., function return values) exist briefly and are often optimized away in modern compilers.
The One Definition Rule (ODR)
C++ enforces one definition per entity across a program. ODR consists of three key rules:
- Within a file:
- Each function, variable, type, or template must have only one definition in a given scope.
- Definitions in separate scopes (e.g., different namespaces) are fine.
- Within a program:
- Each function or variable must have only one definition across files.
- If multiple files define the same function/variable, it causes linker errors.
- Local variables and functions marked
static
orinline
are exceptions.
- Multiple identical definitions are allowed for:
- Types, templates, inline functions, and inline variables.
- As long as each definition is identical across translation units.
Namespaces
- A scope region ensures identifiers remain distinct from names declared elsewhere.
- A namespace introduces a new scope for identifiers, preventing conflicts.
- If an identifier isn’t inside a class, function, or namespace, it belongs to the global namespace.
- The
::
symbol is the scope resolution operator. -
A using directive allows access to namespace members without a prefix:
using namespace std; // Avoid in large projects
The Preprocessor
- After preprocessing, a file becomes a translation unit.
- Preprocessor directives:
- Start with
#
and end with a newline (and not with a semicolon). - Example:
#include
,#define
,#if
.
- Start with
- Macros (
#define
):-
Define object-like macros:
#define IDENTIFIER #define IDENTIFIER substitution_text
- Macros replace occurrences of
IDENTIFIER
withsubstitution_text
. - Function-like macros are discouraged.
-
- Conditional Compilation:
#include <iostream> #define PRINT_JOE int main() { #ifdef PRINT_JOE std::cout << "Joe\n"; // Compiled #endif #ifdef PRINT_BOB std::cout << "Bob\n"; // Skipped #endif return 0; }
-
#if 0
for commenting out blocks:#include <iostream> int main() { std::cout << "Joe\n"; #if 0 // Disable this section std::cout << "Bob\n"; std::cout << "Steve\n"; #endif return 0; }
- Useful for disabling code blocks as nesting multiline (
/* */
) comments is not allowed.
- Useful for disabling code blocks as nesting multiline (
- Scope of
#define
: Preprocessor directives execute before compilation, top to bottom.
Header Files
- A source file should include its paired header:
- Helps catch errors at compile time instead of link time.
- If a function’s return type differs in declaration and definition, the compiler throws an error.
- Overloaded functions (same name, different parameters) are not caught at this stage.
- Some necessary definitions may be in the header, making it mandatory to include.
- Angled Brackets (
<>
) vs. Double Quotes (""
):-
#include <file>
: Searches system directories (used for standard headers). -
#include "file"
: Searches current directory first, then system directories.
-
- Why doesn’t
<iostream>
have.h
?- Old C++ standard used
<iostream.h>
, which defined everything in the global namespace. - The ANSI committee moved all standard library identifiers into the
std
namespace. - New-style headers omit
.h
to differentiate from old headers.
Header Type Naming Convention Example Namespace C++ Specific (New) <xxx>
<iostream>
std
C Compatibility (New) <cxxx>
<cstddef>
std
(required), global (optional)C++ Specific (Old) <xxx.h>
<iostream.h>
Global C Compatibility (Old) <xxx.h>
<stddef.h>
Global (required), std
(optional) - Old C++ standard used
-
Including headers from other directories:
g++ -o main -I./source/includes main.cpp
Enjoy Reading This Article?
Here are some more articles you might like to read next: