0

I'm doing the following problem :

Add on to your Rectangle class from last time:

1)Create a new class TestRect which is a friend class of Rectangle. Inside this class, implement a member function called TestRect::tester, which takes a rectangle as a parameter and tests that both length and width are > 0.

2)Create a main() function which makes three rectangles r1, r2, and r3, each of which has length and width 20. Then call your TestRect::tester function on each of these rectangles and print out the result

I think I did part 1) correctly but part 2) does not give me the output I'm looking for. I do not know how to fix my code from the following output I got :

cppcompile rectEnhanceStaticFriends
Undefined symbols for architecture x86_64:
  "TestRect::tester(Rectangle&)", referenced from:
      _main in rectEnhanceStaticFriends.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
cppcompile:15: no such file or directory: ./rectEnhanceStaticFriends

Can you help me how to fix it? Seems a linker issue, that I did not find how to fix it. Thank you for reading through. (Ps: I compile with VSC) Here is my code :

rectEnhanceStaticFriends.cpp

#include <iomanip>
#include <cstring>
#include <string>
#include "rect.h"
using namespace std;

int main()
{

    Rectangle::setYards(100);
    Rectangle r1(20, 20, "Kitchen");
    Rectangle r2(20, 20, "Bathroom");
    Rectangle r3(20, 20, "Office");
    TestRect tr;

    cout << "Test on r1: " << tr.tester(r1) << endl;
    cout << "Test on r2: " << tr.tester(r2) << endl;
    cout << "Test on r3: " << tr.tester(r3) << endl;

    Rectangle house[] = {Rectangle(10, 12, "Kitchen"),
                         Rectangle(20, 20, "Bedroom"),
                         Rectangle(8, 12, "Offce")};

    for (int i = 0; i < 3; i++)
    {

        if (strcmp(house[i].printName(), "Offce") == 0)
        {
            // cout << "oui\n";
            house[i].setName("Office");
        };

        cout << "Area for " << house[i].printName() << " is : " << house[i].getArea() << endl;
    }

    if (house[1].getArea() > house[2].getArea() && house[1].getArea() > house[3].getArea())
    {
        cout << house[1].printName() << " has the biggest area.\n";
    }
    else if (house[2].getArea() > house[1].getArea() && house[2].getArea() > house[3].getArea())
    {
        cout << house[2].printName() << " has the biggest area\n";
    }
    else
    {
        cout << house[3].printName() << " has the biggest area\n";
    }

    //there is an error house[3] go beyond the array..
    return 0;
}

testRect.h

#ifndef TESTRECT_H
#define TESTRECT_H

class Rectangle; //forward declaration of class Rectangle

class TestRect
{
public:
    bool tester(Rectangle &);
};

#endif

testRect.cpp

#include <iostream> //
#include <iomanip>
#include <string>
#include "testRect.h"
#include "rect.h"

bool TestRect::tester(Rectangle &r)
{
    bool testResult = false;
    if (r.width > 0 && r.length > 0)
        testResult = true;
    return testResult;
}

rect.h

// Rec header file
#ifndef RECT_H
#define RECT_H
#include "testRect.h"

class Rectangle
{
private:
    double width;
    double length;
    char *name;
    static double yardsAvail; //indicate how many yards of perimeter are available to make rectangle
    void initName(const char *n);
    void initName(const char *n, int size);

public:
    //constructors
    Rectangle();
    Rectangle(double, double,
              const char *);
    //destructor
    ~Rectangle() { delete[] name; };
    void setWidth(double);
    void setLength(double);
    void setWidth(char *);
    void setLength(char *);
    void setName(const char *);
    int getWidth() const;
    int getLength() const;
    double getArea() const;
    char *printName() const
    {
        return name;
    }
    //added parts
    static void setYards(double);
    friend class TestRect;
    friend bool TestRect::tester(Rectangle &);
};
double Rectangle::yardsAvail = 0; //added parts

#endif

rect.cpp

#include <iostream> //
#include <iomanip>
#include <string>
#include "rect.h"
#include "testRect.h"
using namespace std;

Rectangle::Rectangle()
{
    width = 0;
    length = 0;
    initName("Default");
}

Rectangle::Rectangle(double x, double y, const char *z)
{
    width = x;
    length = y;
    initName(z);

    double yardsReqd = 2 * x + 2 * y;
    if (yardsAvail - yardsReqd < 0)
    {
        cout << "Not enough yard..\n";
        width = 0;
        length = 0;
    }

    yardsAvail -= yardsReqd;
}

void Rectangle::initName(const char *n)
{
    name = new char[258];
    strcpy(name, n);
};

void Rectangle::initName(const char *n, int size)
{
    name = new char[size];
    strcpy(name, n);
};

void Rectangle::setWidth(double w)
{
    width = w;
}

void Rectangle::setLength(double l)

{
    length = l;
}

void Rectangle::setName(const char *newname)
{
    //newname.newName = "Office";
    strcpy(name, newname);
}

double Rectangle::getArea() const
{
    return width * length;
}

//added part
void Rectangle::setYards(double y)
{
    yardsAvail = y;
}
  • How are you compiling and linking these files? "With VSC" is not enough information to go on. Do you know the command line instruction VSC is using to compile and link? If not, do you have your tasks.json file? – Nathan Pierson Aug 19 '21 at 03:31
  • I used this page in order to be able to compile in c++, until now I had no pb compiling my other files from previous work: https://stackoverflow.com/questions/58549853/compiling-header-files-for-c-using-vscode-code-runner –  Aug 19 '21 at 03:46
  • Quick and dirty test: introduce an obvious syntax error into your definition of `TestRect::tester(Rectangle&)` and make sure the compiler chokes on it. If the compiler does not choke, you are not compiling that file. – JaMiT Aug 19 '21 at 04:08
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – JaMiT Aug 19 '21 at 04:09
  • Actually, it does not choke on it.. –  Aug 19 '21 at 04:18
  • I think I'm moving on the right direction on solving the issue. I did include `#include "testRect.h"` and I got the following output : `duplicate symbol 'Rectangle::yardsAvail' in: rect.o testRect.o duplicate symbol 'Rectangle::yardsAvail' in: rect.o rectEnhanceStaticFriends.o ld: 2 duplicate symbols for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) cppcompile:15: no such file or directory: ./rectEnhanceStaticFriends`. Any help please ? I have been looking through but most of the topic related concerned Xcode... –  Aug 20 '21 at 08:52
  • @siid_14 Your "duplicate symbol" error is [a separate issue](https://stackoverflow.com/questions/1858571/c-duplicate-symbol-error-when-defining-static-class-variable-in-xcode). Note that this demonstrates one reason we ask for a **minimal** reproducible example in all debugging questions. It is not uncommon to have more than one bug in a program. Creating a [mre] is supposed to isolate the bug you are looking at. – JaMiT Aug 20 '21 at 10:28

0 Answers0