ProgrammingC++ Backend Developer

What approaches to declaring and defining member functions of a class exist in C++? What are the differences between declaration inside a class, definition inside a class, and definition outside a class? How does this affect inline implementation?

Pass interviews with Hintsage AI assistant

Answer.

In C++, a member function of a class can be declared:

  • Inside the class (inline definition):

    class A { void foo() { /* ... */ } // directly inside the class };

    Such functions are considered implicitly inline.

  • Inside the class (only declaration):

    class A { void foo(); // only declaration }; void A::foo() { /* ... */ } // definition outside the class

Difference:

  • Definition inside the class (“in place”) automatically assumes inline, the compiler may embed such a function directly into the code where it is called.
  • Definition outside the class is not automatically inline without explicit indication (inline), although the keyword can be added:
    inline void A::foo() { /* ... */ }
  • Declaration outside the class is required when the definition is separated, for instance, in a .cpp file for speeding up compilation and separating the interface from the implementation.

Advantages and disadvantages of approaches:

  • Definition inside the class is convenient for small, frequently called functions.
  • For large methods or methods that change separately, it is more efficient to provide only a declaration in the class and the definition in the .cpp.

Trick question.

Will a function defined inside a class always be actually inlined by the compiler?

Answer: No. The inline keyword (including implicit assignment when defined inside a class) is merely a suggestion to the compiler. The compiler can ignore this advice if it considers the function too complex or unworthy of inlining.


Examples of real errors due to ignorance of the topic nuances.


Story 1

In a large project, member functions were defined as inline inside header files and included in thousands of translation units, resulting in increased compilation time several times over, and the binary size increased due to code duplication — the compiler does not always merge identical machine implementations.


Story 2

In an attempt to speed up execution, the developer moved all class logic into the declaration (in the .h file). This caused the entire project to be rebuilt when a function changed, not just the individual files (which were actually affected by the integration).


Story 3

A new team member placed long serialization and file handling methods directly into the declaration of the template class, causing random error propagation across all TUs and an excessive increase in the size of the executable file without a performance boost.