Tutorials Logic, IN info@tutorialslogic.com

C++ Functions, Parameters, Overloads, and Defaults

Functions Define Contracts

A function gives an operation a name, parameter types, a return type, and a scope. A useful function does one coherent job and makes invalid or exceptional outcomes visible in its interface.

Pass small value types by value, read larger objects through const reference, use a non-const reference only for an intentional output or mutation, and use a pointer when absence is meaningful. Return values are usually clearer than output parameters.

Overload by Meaningful Type Differences

Overload resolution uses the argument types and available conversions, not the return type. Defaults are substituted at the call site and should normally appear once in the public declaration.

One function with a default policy

One function with a default policy
#include <iostream>
#include <string>

std::string repeat(const std::string& text, int count = 2) {
    std::string result;
    for (int i = 0; i < count; ++i) result += text;
    return result;
}

int main() {
    std::cout << repeat("go") << '\n';
    std::cout << repeat("ha", 3) << '\n';
}
Output
gogo
hahaha

inline Is Not a Speed Command

The inline specifier permits identical definitions in multiple translation units; compilers decide whether to inline calls. Define small header functions inline when linkage rules require it, not as a performance promise.

  • Avoid overload sets that differ only through surprising conversions.
  • Use [[nodiscard]] when silently ignoring a result is likely a bug.
  • Keep ownership visible in parameter types.

Choose a Parameter-Passing Contract

A function signature should reveal whether an argument is copied, observed, modified, optional, or consumed. Pass small scalar values by value. Pass large read-only objects by const reference. Use a non-const reference only when mutation is an intentional result, and use a pointer or optional-like type when absence is valid.

Overloads must represent meaningfully different call shapes. Avoid overload sets where integer conversions, default arguments, or braced initialization make the selected function surprising. Keep default arguments in one declaration and prefer a named options type when several Boolean or numeric defaults obscure the call.

  • Use T when the function needs its own value or will move from a cheap-to-move argument.
  • Use const T& for a required, read-only object whose copy is not trivial.
  • Use T& for a required object that the function deliberately updates.
  • Use const T* or T* only when nullptr has a defined meaning.
  • Return a value for a new result; do not return references to temporary or local objects.

Make read, write, and optional parameters visible

Make read, write, and optional parameters visible
#include <string>
#include <utility>

struct Profile {
    std::string displayName;
};

std::string greeting(const Profile& profile) {
    return "Hello, " + profile.displayName;
}

void rename(Profile& profile, std::string name) {
    profile.displayName = std::move(name);
}

bool hasProfile(const Profile* profile) {
    return profile != nullptr;
}

The signatures distinguish observation, mutation, value transfer, and optional access before reading the bodies.

Before you move on

Function Contract Review

5 checks
  • Inputs and outputs are explicit.
  • Parameter passing matches ownership and mutation.
  • Defaults appear in one declaration.
  • Overloads are unambiguous.
  • Failure behavior is documented.

Function Questions

Ambiguity occurs when two overloads require conversions of equal rank, so neither is a better match. Integer literals, implicit numeric conversions, and default arguments commonly trigger it.

Default arguments are substituted at the call site, so repeating or changing them across declarations can create errors or inconsistent behavior between translation units. Put the default on the public declaration and omit it from the definition.

No. <code>inline</code> primarily permits identical definitions in multiple translation units, which is why small header-defined functions use it.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.