c++class-memberssource-separation

In C++, why must class member functions be defined outside class for separate compilation?


The following is a simple example for separate compilation:

// mod.cpp
#include <cstdio>

class MyModule {
public:
    void print_msg();
};

void MyModule::print_msg() {
    printf("hello from module\n");
}
// main.cpp
class MyModule {
public:
    void print_msg();
};

int main() {
    MyModule a;
    a.print_msg();
}

We can compile and run it with

g++ main.cpp -c -o main.o
g++ mod.cpp -c -o mod.o
g++ main.o mod.o -o main
./main

The above works fine, but if I move the definition of MyModule::print_msg inside the class:

// mod.cpp
#include <cstdio>

class MyModule {
public:
    void print_msg() { printf("hello from module\n"); }
};

I get an 'undefined reference' error for compiling main:

g++ main.cpp -c -o main.o  # OK
g++ mod.cpp -c -o mod.o    # OK
g++ main.o mod.o -o main   # undefined reference error
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x23): undefined reference to `MyModule::print_msg()'
collect2: error: ld returned 1 exit status

I know that the former is the standard way and the class definition should go to a header file, but I wonder why the second method doesn't work.


Solution

  • Functions defined inside the class are implicitly inline. C++ requires:

    The definition of an inline function [or variable (since C++17)] must be reachable in the translation unit where it is accessed.

    Since you only defined it in mod.cpp, no definition is reachable in main.cpp, and compilation fails.

    Typically, you'd put the definition of the class, and the definition of all functions defined within it, in a header file to be included by all users of the class. The functions defined outside the class then go in a .cpp file. That way a single consistent definition of all the inline functions is available to all users of the class, and you're not repeating the definition of the class in each .cpp file manually.