c++compiler-errorscompilationlinker-errors

Why does the linker not work correctly when definitions are implemented in cpp file


I do not understand how to compile c++ code correctly. I have a test file using an example class and I continue to get the error:

user@MacBook-Pro Online-Order-OOP-Project % clang++ -std=c++11 -o test.out test.cpp
Undefined symbols for architecture arm64:
  "Point::getX()", referenced from:
      _main in test-3f2ef3.o
  "Point::Point()", referenced from:
      _main in test-3f2ef3.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

It was my understanding that using the #include statements would handle the linking for me. How do I make this compile correctly?

Here is the test.cpp file:

#include "Point.h"
#include <iostream>


int main() {
    Point point;
    std::cout << point.getX() << std::endl;
    return 0;
}

Here is the Point.h file:

#ifndef POINT_H
#define POINT_H

class Point {
    private:
        int x;
        int y;

    public:
        Point()  ;
        int getX() ;
        int getY() ;

};


#endif

and the Point.cpp file:

#include "Point.h"

Point::Point() {
            this->x = 0;
            this->y = 0;
} 
int Point::getX() {
    return this->x;
} 
int Point::getY() {
    return this->y;
} ;

Solution

  • Now seems like a good time to learn how the compiler really works, and about the concepts of translation units.

    In short, a translation unit is a single source file with all included header files. It's the basic unit that the compiler is working with. The compiler will only know what is in the translation unit it's currently process, nothing else.

    The program clang++ that you run isn't actually the compiler. Instead it's a front-end driver program which invokes the tools needed to build your source into an executable program.

    The process of building a source file into a program follows multiple steps:

    1. Preprocess the source file.

      This includes all header files and expands all macros.

      This step is usually embedded into the actual compiler, and not separate and distinct.

    2. Actual compilation.

      This takes the translation unit, compiles it into machine code, and outputs an object file.

    3. Linking.

      This is where all object files and libraries are combined to form the final executable program.

    As mentioned above, step 1 and 2 are usually combined, but in the C++ specification is still considered separate phases. Step 2 (with step 1) and step 3 are usually performed by two different programs, that doesn't really know anything about each other.

    And here comes the part that leads to your problem: You were building only the test.cpp source file. The clang++ program will tell the compiler to build that single file into an object file, and then tell the linker to use that single object file to create the executable program. No program will know about the Point.cpp source file.

    You need to explicitly tell clang++ about all source files it should use.