Functions in C++

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?
    C++ function declarations, definitions and calls. Source: Devopedia 2022.
    C++ function declarations, definitions and calls. Source: Devopedia 2022.

    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?
    C versus C++ function definition syntax. Source: IBM 2021, pp. 200.
    C versus C++ function definition syntax. Source: IBM 2021, pp. 200.

    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?
    Three ways to pass arguments. Source: Devopedia 2022.
    Three ways to pass arguments. Source: Devopedia 2022.

    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?
    Function overloading vs overriding. Source: Devopedia 2022.
    Function overloading vs overriding. Source: Devopedia 2022.

    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).

References

  1. Alex. 2022. "11.2 — Function Pointers." Tutorial, Learn C++, January 18. Accessed 2022-01-24.
  2. Coleman, Rick. 2019. "Getting the work done: Functions." CS 307, Object Oriented Programming, The University of Alabama in Huntsville. Accessed 2022-01-24.
  3. Cppreference. 2021. "History of C++." Cppreference, December 30. Accessed 2021-12-27.
  4. Cppreference. 2022. "Functions." Cppreference, January 9. Accessed 2022-01-14.
  5. Eckel, Bruce. 2000. "Thinking In C++" Prentice Hall Inc. Accessed 2022-01-18.
  6. FSU. 2022. "Functions 1: Predefined and Value-Returning Functions." Chapter 6 in: C++ Notes, Dept. of CS, Florida State University. Accessed 2022-01-14.
  7. IBM. 2021. "z/OS XL C/C++ Language Reference." v2.5, IBM Corporation, September 12. Updated 2021-09-30. Accessed 2022-01-23.
  8. ISO. 2011. "ISO/IEC 14882:2011 Information technology — Programming languages — C++." Edition 3, September. Accessed 2022-01-07.
  9. ISO. 2017. "ISO/IEC 14882:2017 Information technology — Programming languages — C++." Edition 5, December. Accessed 2022-01-07.
  10. Kessler, Andre. 2014. "C++ Coding Standards and Best Practices." In: Effective Programming in C and C++, 6.S096, MIT, January 8-31. Accessed 2022-01-14.
  11. Microsoft. 2021a. "Functions (C++)." Documentation, Visual Studio 2022, Microsoft, August 17. Accessed 2022-01-14.
  12. Microsoft. 2021b. "Virtual Functions." Documentation, Visual Studio 2022, Microsoft, August 3. Accessed 2022-01-14.
  13. Microsoft. 2021c. "constexpr (C++)." Documentation, Visual Studio 2022, Microsoft, August 3. Accessed 2022-01-20.
  14. Niyaz. 2008. "How do you pass a function as a parameter in C?" StackOverflow, August 13. Updated 2020-08-06. Accessed 2022-01-14.
  15. StackOverflow. 2013. "Why using the const keyword before and after method or function name?" StackOverflow, May 8. Accessed 2022-01-20.
  16. Stroustrup, Bjarne. 1993."A history of C++: 1979–1991." HOPL-II: The second ACM SIGPLAN conference on History of programming languages, pp. 271-297, April. doi: 10.1145/154766.155375. Accessed 2022-01-20.
  17. Stroustrup, Bjarne. 2020. "Thriving in a crowded and changing world: C++ 2006–2020." Proceedings of the ACM on Programming Languages, vol. 4, Issue HOPL, Article No. 70, pp. 1-168, June. Accessed 2022-01-07.
  18. Stroustrup, Bjarne. 2021. "Bjarne Stroustrup's FAQ." July 23. Accessed 2022-01-07.
  19. Sun Microsystems. 2000. "Templates." Chapter 4 in: C++ Programming Guide, Sun WorkShop 6, Part No. 806-3571-10, Sun Microsystems, May. Accessed 2022-01-14.
  20. Supanich, Joseph, trans. 1992. "Chapter 9: Functions." In: Henricson, Mats and Erik Nyquist, Programming in C++, Rules and Recommendations, Ellemtel Telecommunication Systems Laboratories. Accessed 2022-01-14.
  21. Vandevoorde, David, and Nicolai M. Josuttis. 2002. "C++ Templates." Addison Wesley. Accessed 2022-01-14.
  22. Vats, Rohan. 2021. "Function Overriding in C++." Blog, Upgrad, May 25. Accessed 2022-01-14.

Further Reading

  1. Price, Clayton. 2022. "8.0 Function Basics." CS1570, Programming C++, Missouri University of Science and Technology. Accessed 2022-01-24.
  2. Cplusplus. 2022. "Functions." Tutorial, cplusplus. Accessed 2022-01-15.
  3. Allain, Alex. 2022. "Functions." cprogramming. Accessed 2022-01-15.
  4. Microsoft. 2021a. "Functions (C++)." Documentation, Visual Studio 2022, Microsoft, August 17. Accessed 2022-01-14.
  5. IBM. 2021. "Functions." z/OS XL C/C++ Language Reference, v2.5, IBM Corporation. Accessed 2022-01-24.
  6. IBM. 2021. "Virtual functions (C++ only)." z/OS XL C/C++ Language Reference, v2.5, IBM Corporation. Accessed 2022-01-24.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
3
5
2229
22
3
2064
2380
Words
1
Likes
2156
Hits

Cite As

Devopedia. 2022. "Functions in C++." Version 25, January 24. Accessed 2023-11-12. https://devopedia.org/functions-in-c-plus-plus
Contributed by
2 authors


Last updated on
2022-01-24 17:30:40
  • C++ Templates
  • C++ Constructors and Destructors
  • Scope in C++
  • C++ Operators
  • C++ Inheritance
  • C++ Data Types