1

I'm trying to compile a C++ program "test.cpp" that includes a custom file "Cars.h" using VS Code. However it causes a build error even though I'm pretty sure I did everything right.

My directory structure:

Test
├── .vscode
│   ├── tasks.json
├── include
│   ├── Cars.cpp
│   └── Cars.h
├── test.cpp

test.cpp

#include <iostream>
#include "include/Cars.h"

using namespace std;

int main(){
    Cars c;
    cout << "Hello!" << endl;
    c.printcars();  
}      

Cars.cpp

#include <iostream>

class Cars{

    public:
        void printcars(){
            std::cout << "Cars" << std::endl;
        }

};

Cars.h

#ifndef CARS_H
#define CARS_H

class Cars {
    public:
        void printcars();

};

#endif

tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "buildFile",
            "command": "g++",
            "args": [
                "-o",
                "${fileBasenameNoExtension}.exe",
                "${file}",
                "${workspaceFolder}\\include\\*.cpp",
                "${workspaceFolder}\\include\\*.h",
                "-I${workspaceFolder}\\include"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        }
        
    ]
}

Error:

test.cpp:(.text+0x37): undefined reference to `Cars::printcars()'
collect2.exe: error: ld returned 1 exit status

Build finished with error(s).

 *  The terminal process terminated with exit code: -1. 
 *  Terminal will be reused by tasks, press any key to close it. 

I am certain that it's a linker error, since the program runs perfectly when I include Cars.cpp instead of Cars.h. However this is a test and I am required to include the header file only.

AlexWatson
  • 13
  • 3
  • What command did you use to compile it? The compiler is searching for `Cars::printcars()` but can't find it. Try `g++ Cars.h Cars.cpp test.cpp -Wall -Werror -pedantic -o prog` – underloaded_operator May 30 '23 at 07:47
  • Side note, but put cars.cpp in the same directory as main. Or better compile into a seperate static library first so you can also link your code with a unit test excecutable. – Pepijn Kramer May 30 '23 at 07:50
  • @TheCompile-TimeComedian i have a keyboard shortcut for running the task buildFile. Also I tried your command and got the same error :( – AlexWatson May 30 '23 at 07:52
  • @AdithyaPrakash make sure they're in the same directory first, after that run the command I gave you or the keyboard command. They essentially do the same thing, build your executable. – underloaded_operator May 30 '23 at 07:55
  • Please read: https://stackoverflow.com/q/12573816/1387438 – Marek R May 30 '23 at 08:08
  • Note that contents of your `Cars.cpp` is violation of One Definition Rule. – Marek R May 30 '23 at 08:10

2 Answers2

2

Your main issues are,

  1. You have not included the header file within your Cars.cpp file, so the linker has no idea where your defined code is for that Cars.h file.
  2. In Cars.cpp, you are not defining the function that you've declared within the class in Cars.h

To fix these, you must first include the header file within your Cars.cpp file

so it would look like this..

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

class Cars {

public:
    void printcars() {
        std::cout << "Cars" << std::endl;
    }

};

And you need to define the function within Cars.cpp like so:

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

void Cars::printcars() {
    std::cout << "Cars" << std::endl;
}

This should hopefully fix your linker error.

0xy18
  • 21
  • 2
  • I think it's slightly confusing to show changes needed to the cpp file in two stages, certainly confused me, because I thought the first code sample was the header file. – john May 30 '23 at 08:05
  • Right. I'm still new to answering questions on here and I'm still not used to how answers are meant to be structured. Greatly appreciate the feedback. – 0xy18 May 30 '23 at 08:13
0

There's a few things wrong. But the main one is that you have defined the class Cars twice, once in cars.h and once in cars.cpp.

cars.cpp should look like this

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

void Cars::printcars(){
    std::cout << "Cars" << std::endl;
}

Don't define Cars twice, instead include cars.h in cars.cpp and use an out of class definition for Cars::printcars.

The other thing I don't like is your tasks.json file. Don't use ${file}, that is the file you are currently editing. I'm sure you can see that might cause problems, you can only build your code if you happen to be editing main.cpp. Secondly don't compile header files, so remove "${workspaceFolder}\\include\\*.h"

Something like

        "args": [
            "-o",
            "${fileBasenameNoExtension}.exe",
            "${workspaceFolder}\\main.cpp",
            "${workspaceFolder}\\include\\*.cpp",
            "-I${workspaceFolder}\\include"
        ],

seems right to me (but I'm no expert on VSCode).

john
  • 85,011
  • 4
  • 57
  • 81