Undefined symbols for architecture x86_64

I'm making a rectangle program, split in 3 files :

rectangle.cpp
Rectangle.h
rectangleProgram.cpp

First I did the program in one piece without any errors. Then I split it and I got the following error :



Undefined symbols for architecture x86_64:
  "Rectangle::setWidth(double)", referenced from:
      _main in rectangleProgram-4857c8.o
  "Rectangle::setLength(double)", referenced from:
      _main in rectangleProgram-4857c8.o
  "Rectangle::getPerimeters() const", referenced from:
      _main in rectangleProgram-4857c8.o
  "Rectangle::getArea() const", referenced from:
      _main in rectangleProgram-4857c8.o
  "Rectangle::getWidth() const", referenced from:
      _main in rectangleProgram-4857c8.o
  "Rectangle::isSquare() const", referenced from:
      _main in rectangleProgram-4857c8.o
  "Rectangle::getLength() const", referenced from:
      _main in rectangleProgram-4857c8.o
ld: symbol(s) not found for architecture x86_64


I have been looking through, but can't see what I did wrong despite the fact it worked in one piece (all together in one file)

How to fix this?

Rectangle.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Rectangle header file
#ifndef RECTANGLE_H
#define RECTANGLE_H

class Rectangle
{
private:
    double width;
    double length;

public:
    void setWidth(double);
    void setLength(double);
    double getWidth() const;
    double getLength() const;
    double getArea() const;
    double getPerimeters() const;
    bool isSquare() const;
};
#endif 


rectangle.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include "Rectangle.h"
using namespace std;

// set the width of the rectangle
void Rectangle::setWidth(double w)
{
    if (w > 0)
        width = w;
    else
    {
        cout << "ERROR: invalid width!\n";
        exit(1);
    }
}
// set the length of the rectangel
void Rectangle::setLength(double len)
{
    if (len > 0)
        length = len;
    else
    {
        cout << "ERROR: invalid length!\n";
        exit(1);
    }
}

//get the width of the rectangle
double Rectangle::getWidth() const
{
    return width;
}

//get the length of the rectangle
double Rectangle::getLength() const
{
    return length;
}

//get the area of the rectangle
double Rectangle::getArea() const
{
    return width * length;
}

//return the perimeter of the rectangle
double Rectangle::getPerimeters() const
{
    return 2 * width + 2 * length;
}

//return the perimeter of the rectangle
bool Rectangle::isSquare() const
{
    if (length == width)
    {
        return true;
    }
    else
        return false;
}


rectangleProgram.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream> //
#include "Rectangle.h"
using namespace std;

int main()
{
    Rectangle r;

    r.setWidth(3);
    r.setLength(5);

    cout << "width: " << r.getWidth() << endl;
    cout << "length: " << r.getLength() << endl;
    cout << "area: " << r.getArea() << endl;
    cout << "perimeters: " << r.getPerimeters() << endl;
    cout << "Square ? " << r.isSquare() << endl;

    return 0;
}
You didn't say how you're compiling, but assuming g++ from the command line, you need to say something like:

 
g++ -std=c++17 -Wall -Wextra -pedantic rectangle.cpp rectangleProgram.cpp

(You might want -std=c++14 or even -std=c++11 instead.)

Each cpp file is compiled to a separate object (.o) file. Then the two object files are "linked" together to create the executable. With the above command the object files are deleted after they are linked into the executable, so you won't see them.

Alternatively, you can compile the cpp files to object files separately with the -c switch, then link them in a separate step. This is useful when your program has dozens of cpp files. That way a change to a single cpp file will only require the recompilation of one file. Then all the object files can be linked, which is a relatively simple and quick operation (mostly just copying the files and "resolving" the references to functions and objects in the other files).

1
2
3
g++ -std=c++17 -Wall -Wextra -pedantic -c rectangle.cpp         # creates rectangle.o
g++ -std=c++17 -Wall -Wextra -pedantic -c rectangleProgram.cpp  # creates rectangleProgram.o
g++ rectangle.o rectangleProgram.o -o rectangle                 # creates rectangle 

If you're on Windows then you probably want to call it rectangle.exe.

BTW, I don't understand why getPerimeters() is plural. Isn't there only one perimeter?

Also, isSquare() can be:

1
2
3
4
bool Rectangle::isSquare() const
{
    return length == width;
}

And you probably want a constructor or two:

1
2
3
4
5
6
7
8
9
Rectangle::Rectangle(int size)
    : width(size), length(size)
{
}

Rectangle::Rectangle(int width_in, int length_in)
    : width(width_in), length(length_in)
{
}

Last edited on
Perimeters should be singular (sorry).

Also, I tried all your commands, none of them work...

I'm gonna give more details. I'm using macOS and compile via Visual Studio Code using the extension Code Runner in order to compile. Maybe that information will be useful.

Maybe my question should be by now, how to compile header files for C++ using VSCode Code Runner?
typically you add the code (.cpp and .h, or on mac, .cc and .h may be in use) to the project and build the project.

so rectangle and rectangleprogram would BOTH include rectangle.h.
rectangleprogram and rectangle cpp files would BOTH be in the project.
rectangle.h may be in the project or in the include path (its better if its in the project so it is indexed by the tools for easy opening and editing).
with all that, mashing build should do it. It looks like you are close.
siid14,
You don't compile header files separately; you #include them in the driver and implementation, and your compiler should automatically compile them into the executable with the others.

Are you using c++ or g++ for compiling, or are you using an IDE? I would try using g++ or c++ in Terminal, and use this format:

c++ -std=c++2a -g -o executable program implementation

or
g++ -std=c++2a -g -o executable program implementation


The -g flag is for debugging, you can leave that out if you don't need to debug. The -o flag sets the name of the executable; if you leave it out, it defaults to a.out.

executable is whatever you want to call your exec,
program is the name of your driver program, like "rectangleProgram.cpp", and
implementation is the name of your class implementation file, like "rectangle.cpp.

dutch,
Your command is backwards; it should be:
g++ -std=c++17 -Wall -Wextra -pedantic rectangleProgram.cpp rectangle.cpp


The driver comes first, then the executable. At least that's how my g++ manual says to do it. If it works the way you do it, then you can ignore what I said.
When I applied what you say agent max I got the following error :

c++ -std=c++2a-Wall -Wextra -pedantic rectangleProgram.cpp rectangle.cpp

error: invalid value 'c++2a-Wall' in '-std=c++2a-Wall'
note: use 'c++98' or 'c++03' for 'ISO C++ 1998 with amendments' standard
note: use 'gnu++98' or 'gnu++03' for 'ISO C++ 1998 with amendments and GNU extensions' standard
note: use 'c++11' for 'ISO C++ 2011 with amendments' standard
note: use 'gnu++11' for 'ISO C++ 2011 with amendments and GNU extensions' standard
note: use 'c++14' for 'ISO C++ 2014 with amendments' standard
note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard
note: use 'c++17' for 'ISO C++ 2017 with amendments' standard
note: use 'gnu++17' for 'ISO C++ 2017 with amendments and GNU extensions' standard
note: use 'c++2a' for 'Working draft for ISO C++ 2020' standard
note: use 'gnu++2a' for 'Working draft for ISO C++ 2020 with GNU extensions' standard
error: invalid value 'c++2a-Wall' in '-std=c++2a-Wall'
note: use 'c++98' or 'c++03' for 'ISO C++ 1998 with amendments' standard
note: use 'gnu++98' or 'gnu++03' for 'ISO C++ 1998 with amendments and GNU extensions' standard
note: use 'c++11' for 'ISO C++ 2011 with amendments' standard
note: use 'gnu++11' for 'ISO C++ 2011 with amendments and GNU extensions' standard
note: use 'c++14' for 'ISO C++ 2014 with amendments' standard
note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard
note: use 'c++17' for 'ISO C++ 2017 with amendments' standard
note: use 'gnu++17' for 'ISO C++ 2017 with amendments and GNU extensions' standard
note: use 'c++2a' for 'Working draft for ISO C++ 2020' standard


This is one example cause I try other command too with c++98, c++17, c++14, c++11.

I made further research through the use of the extension Code Runner [an extension that make my code run in c++ in Visual Studio Code (works perfectly for c++ without header file such as rectangle.h for example)]

Through the executor map (.json file) of Code Runner, I have for c++ the following :
"cpp": "cd $dir && g++ $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt"

I hope this would help you guys to guide and make those c++ files compile finally..
Last edited on
-std=c++2a-Wall
These should be two different compiler flags, separated by whitespace.
-std=c++2a (enable supported C++20 features)
-Wall (enable most warnings)
Last edited on
@siid14,
Ganado is correct.

Copy and paste this command into your command line:
c++ -std=c++2a -Wall -Wextra -pedantic rectangleProgram.cpp rectangle.cpp


It should work. If it doesn't, then your compiler is broken.

Have a good day!
max
Last edited on
Topic archived. No new replies allowed.