# Functions in C++

## Summary


A function is a block of code that typically performs a specific task. Functions help manage complexity in a large program by breaking it down into smaller manageable parts. Functions make programs easier to read, debug and understand. They introduce modularity into a program. 

Within a given program scope, each function has a unique name. A function can be called with arguments. After performing its operations on those arguments, a function can return a value. Arguments and return value are optional. 

C++ adopts and extends C functions in terms of syntax and functionality. Since C++ is object-oriented, we also have member functions that are part of classes. C++ standard libraries supply a number of functions that developers can use. In addition, developers can define and call their own custom functions. Every program requires and starts execution from the `main()` function.

## Discussion

### What are the different components of function?

A function consists of three components:

    + **Function Prototype/Declaration**: Declares the function before it's used. The prototype tells the compiler about the function's return type and the arguments passed, which is used to validate function definition and function calls. Arguments need not be named in the prototype. The function declaration itself is not necessary if the function is defined before it is called. Syntax: `return_type function_name (parameter_list);`
    + **Function Definition**: The block of statements enclosed within curly braces. Also called function body. The parameters present in the function definition are called *formal parameters*. Syntax: `return_type function_name (parameter_list) {…}`
    + **Function Call**: Actual call to the function for execution of its body. The parameters present in the function call are called *actual arguments*. Actual arguments replace the formal parameters at the time of the function call. Syntax: `function_name (parameter_list)`The figure shows prototypes of function `rad2deg` and member functions `Sector::Sector` (constructor) and `Sector::degrees`. Code shows the common practice of putting declarations in header files and definitions in CPP source files. When `sector.cpp` is compiled, compiler sees the prototype of `rad2deg` via the inclusion of `utils.h`. 


### How is a C++ function different from a C function?

In C, if function `func` is called before it's declared, compiler assumes the implicit declaration `extern int func();`. C++ requires explicit function declarations. In terms of function definitions, C++ extends the C syntax with try block for exception handling. For member functions, C++ adds constructor initializer, and `=default;` and `=delete;` specifiers. 

In C++ function definitions, parameters need not be named but C requires that all parameters be named. Unnamed parameters can't be referenced in function body. They're simply placeholders for future code evolution. 

In old C, functions could be called by any number or type of arguments, which sometimes resulted in undesired output. For better type checking and safer code, standard C/C++ introduced the prototype. A C++ function prototype with empty argument list implies zero arguments but in C this could mean an indeterminate number of arguments. To denote an empty list consistently in both C and C++, we could use "void" instead, `func_name(void)`. 


### Could you describe C++ storage class specifier, function specifier and return type specifier?

Storage class specifiers determine linkage. If `static`, such a function is visible only within the current translation unit, which is typically the current file. Thus, other files can't access this function. In C, `inline` specifier also makes the function static. In C++, use of `static` is deprecated. Instead, an unnamed namespace should be used. To call a function from other translation units, `extern` can be used, which is also the default when no storage class specifier is mentioned. 

There are many function specifiers. The `inline` specifier inserts code in-place. Member functions can be defined as `virtual`. `constexpr` enables compile-time optimization. `_cdecl` specifies C linkage conventions. `_Export` makes the function available to other modules. `explicit` disables implicit conversions involving constructors. `_Noreturn` indicates that function doesn't return to the caller. 

A function return type can be any value except an array or a function. Pointers to an array or a function may be returned. In C++, a reference can be returned and `void` if nothing is returned. When return type is not specified, by default C functions assume `int` is returned. 


### Could you explain use of specifiers virtual and inline on functions?

Specifier `virtual` is applicable to member functions. Virtual functions in C++ help implement *runtime polymorphism*, which is about designing a unified interface but with different runtime behaviours. A virtual function in the base class presents a unified interface for derived classes and their users. A derived class can override the base class virtual function with its own specialized behaviour. The virtual specifier tells the compiler to check the type of object at the runtime and then call the correct derived class function. 

A pure virtual function is a virtual function without an implementation. It's assigned to zero, `virtual int func () = 0;`. Such a class, called an **abstract class**, can't be instantiated. It's derived class can be instantiated provided the latter defines an implementation of all pure virtual functions of its base classes. 

Specifier `inline` replaces the function call with the function body. This avoids the runtime overhead of a function call at the expense of program size. Member functions defined within class declarations are automatically defined inline. Inline is only a suggestion to the compiler. Compiler is free to ignore it. 


### What is a const and constexpr function?

The `const` *keyword* in C++ is used to prevent accidental modification of the object that it is applied to. The `const` keyword always binds to the left. In case, there's nothing on the left, it binds to the right. We show two examples: 

    + `const T& func();`: Function returns a constant reference to object of type `T`.
    + `int T::func() const;`: Declares a constant member function of class `T`. This function can't modify data members of the class. Note that `const` keyword comes after the function identifier and parameters. In general, this is called *cv\_qualifier\_seq*, referring to `const` and `volatile` member functions. It's part of the function declarator.The `constexpr` *specifier* specifies that the particular value can be evaluated at compile time. By computing the values at compile time, runtime performance can be improved. However, `constexpr` is only a suggestion to the compiler. The compiler may choose to ignore it, particularly when the function doesn't satisfy conditions to yield a constant expression.

In conclusion, `constexpr` is for optimization whereas `const` prevents modification of class data members. `constexpr` can be used for non-member and member functions but `const` is applicable only for member functions. 


### What are the ways to pass arguments to a function?

C++ supports three argument-passing mechanisms:

    + **Call by Value**: Value is copied from the caller and passed into the function. The argument variable at the caller and that within the function occupy different memory locations. The function works on its own copy and any changes are visible only inside the function. The caller's argument variable is not affected.
    + **Call by Reference**: Reference of the caller's argument variable is copied into the function. Due to the reference, the function "refers" to the same object as the caller. If any changes are made, the original value is modified and caller sees those changes.
    + **Call by Pointer**: This is similar to call by reference, except for a legacy syntax coming from C. Pointer contains a low-level memory location of the object. When a pointer is passed, the function "points" to the same object as the caller. If any changes are made, the original value is modified and caller sees those changes.A function can use a mix of the above: some arguments are passed by value, some are by reference and the rest by pointer.


### What's the difference between function overloading and function overriding?

In C++, **function overloading** is a concept in which two or more functions can have the same name but different number or types of parameters. Function overloading is not possible when two C++ functions differ only by the return type. It's achieved at compile time. Function overloading is possible with member functions as well. 

In the case of inheritance, when a derived class overwrites a virtual function in the base class, the concept is referred to as **function overriding**. When function calls are made on base class objects, execution should call the correct function of the applicable derived class. This information is either not available or hard to achieve at compile time. Thus, function overriding is achieved at runtime. 

Where a derived class overwrites a non-virtual function in the base class, then the concept is called **name hiding**. This is achieved at compile time. 


### What's operator overloading in C++?

Examples of operators are `+`, `*`, `>>`, and many more. When such operators are applied to standard types such as integers, strings or floating-point numbers, C++ uses different underlying implementations. Thus, addition of two strings is a different function call compared to addition of two integers. We may say that the operator is overloaded. This is similar to function overloading where the overloaded functions differ by the number or types of arguments. An overloaded operator is called an **operator function**. 

Suppose we define a custom class named `Complx` and wish to add two objects `c1` and `c2` of this class. This is where operator overloading helps. We can create member function of prototype `Complx operator+(const Complx&) const;`. This function would do the actual addition. The function is invoked by `c1 + c2`, where `c2` is passed as argument to member function `c1`. 


### What's a function template in C++?

Suppose we need a function to add two integers and another function to add two floating-point numbers. We can write two uniquely named functions. Or we can write two functions of same name (function overloading) but with differing argument types. With C++ templates, we can achieve this with a single function template. They also enable type-safe code. 

Templates in C++ save developers the trouble of writing duplicated code for different data types. The parameters used in the template definition are of a generic data type and can be replaced by actual ones. 

Templates are instantiated at compile time. The source code contains only one function template but the compiled code contains many functions, each specific to its data type. Instantiation can be implicit or explicit. Developers can also specialize the template with alternative implementations for specific combinations of template arguments. 


### What's a function pointer and what's its usage?

A **function pointer** is used to store the address of a function. With a function pointer, we can dynamically select at runtime a particular function to execute, pass as arguments to other functions or use as return types. It's prototype in C++ takes the form `type(*ptr)(arg_list);`. 

Consider the example `int (*g)(int a);`, where `g` is a pointer to a function that accepts one integer argument and returns an integer. The extra bracket around the pointer name is necessary because in its absence the compiler may interpret it as a function that returns a pointer to an integer.  

A function pointer can be a function argument, `void func(void (*f)(int)) { (*f)(); }`, where `f` is the function pointer. Given `void print(int a);`, `func(print)` is a valid function call. 

C++ also supports **references to functions**. The above example becomes `void func(void (&f)(int)) { f(); }` and the function call is `func(print)`. 


### What are some best practices when using C++ functions?

Following best practices will lead to clean maintainable code:  

    + A function should do only one task. A function that does multiple tasks is hard read, edit and unit test.
    + Use inline functions instead of `#define` pre-processor directive. Don't inline large functions.
    + Specify the return type of a function explicitly. Public functions mustn't return a reference or pointer to a local variable.
    + When using function overloading, have semantic consistency. All overloaded functions should do the same task.
    + Use `const` on an argument if function is not supposed to modify it. Rather than call by value, use `const &` to avoid the runtime overhead of calling the copy constructor and destructor.
    + Prefer call by reference since the code is more readable than call by pointer.
    + Don't assume call arguments will be processed in left-to-right order. No ordering is specified in C++ standard.
    + Code should be self-explanatory. It makes the code easy to understand. Function and variable names should be descriptive of what they do. Comments should be given wherever needed.


## Milestones

Apr  
1979

At Bell Laboratories, inspired by Simula, Bjarne Stroustrup conceives the idea of *C with Classes*. This is later renamed to C++ (1984). 

1980

By now, the language includes base and derived classes with member functions, constructors and destructors, type checking and conversions for function arguments, inline functions, default arguments, and operator overloading for the `=` operator. For type checking, the language introduces `f(void)` as a better syntax to C's relaxed use of `f()`. Functions `call` and `return` are available but these are not accepted into C++ standard in the late 1980s.

1983

**Virtual functions** are introduced into the language. With this feature, its creators start calling it a language for object-oriented programming. 

1985

Stroustrup publishes first edition of his book *The C++ Programming Language*. This becomes the reference for C++ 1.0. Features described in this book include function and operator overloading, references, the keyword `const`, and scope resolution operator. References are introduced mainly to support operator overloading. 

1989

C++ 2.0 is released. This includes support for abstract classes via **pure virtual functions**. Among other additions are better resolution of overloaded functions, `static` member functions, `const` member functions, and overloading of `->` operator. 

1990

Ellis and Stroustrup publish *The Annotated C++ Reference Manual*. This becomes a starting point for C++ standardization. This introduces **templates**, which is added into the C++ standard in September 1991. 

Sep  
2011

ISO publishes the C++11 standard, formally named ISO/IEC 14882:2011. This release includes `constexpr` functions, unnamed function objects called *lambdas*, variadic templates (arbitrary number of arguments), template aliases, and `noexcept` to ensure that the function doesn't throw an exception. 

Dec  
2017

ISO publishes the C++17 standard, formally named ISO/IEC 14882:2017. This introduces a **uniform function call syntax**. A function could be called in the object-oriented way `x.f(y)` or the functional way `f(x,y)`.