0

The Question Posed:

  1. Add the following features to your Shape class of Question 5:

Two private static members shapesCreated and shapesDestroyed, which are to be used to count the total number of Shape objects that have been created and destroyed, respectively. A destructor, which increments the value of shapesDestroyed Modify the class constructor, so that it increments the shapesCreated variable, each time a new Shape object is created. A static method static int shapesCount() that returns the current number of Shape objects still alive. Add a shapeID (non static) member to the Shape class, which is a unique integer id of a shape. Set it’s value using the shapesCreated value on construction, that is, the nth shape created will have its id value equal to n. Add a method int id() to return the id of a Shape object. [15 marks]

Q7. Write two classes Circle and Rectangle that inherit from Shape and correctly implement their constructors to set their radius/coordinates, as appropriate. They must also implement the info() method inherited from Shape. Their info() method should return a string containing the shape’s id, the shape’s coordinate information and the shape’s color.

[15 marks]

My Code:

#include <iostream>
#include <sstream>
using namespace std;
int shapeIDCounter = 0,createDestroyCounter=0;

class Colour{
    private:
        double red,blue,green;

    public:
        double rMax;


        Colour(double a,double b,double c){
            red = a;
            blue = b;
            green = c;


        }
        // #1
        Colour(const Colour& clr){
            red = clr.r();
            blue = clr.b();
            green = clr.g();
            cout << "\nConstructed colour by copying anothers properties";
        }

        double r() const {
            return red;
            }

        double b() const {
            return blue;
            }

        double g() const {
            return green;
            }

        string toString(){
        string info = "The value for the colour components are: (";
        ostringstream convertR;
        convertR << r();
        info += convertR.str();
        ostringstream convertB;
        info += ",";
        convertB << b();
        info += convertB.str();
        ostringstream convertG;
        info += ",";
        convertG << g();
        info += convertG.str();
        info += ")";
        return info;
        }

        static Colour maxRed(Colour carr[], int size){
            double rMax;
            rMax = carr[0].r(); //initial case of first element
            for(int i = 1;i<=size;i++){
                if(carr[i].r() > carr[i-1].r()){
                    rMax= carr[i].r();
                }}
                cout << "\nThe largest Red Value in the array is: " << rMax;

        }
};
//the abstract class

class Shape: public Colour{

    protected:
    static int shapesCreated;
    static int shapesDestroyed;
    protected:
    int shapeID;




    public:

    Shape(double a,double b,double c):Colour(a,b,c){
        setCreateDestroy(); //used to initialize created & destroyed values
        shapesCreated++;
        shapeIDCounter++;
        shapeID = shapeIDCounter;
    }

    void setCreateDestroy(){
        if(createDestroyCounter == 0){
        shapesCreated = 0;
        shapesDestroyed = 0;
        createDestroyCounter = 1;
    }
    }

    virtual string info()=0; //making the class abstract

    ~Shape(){
    shapesDestroyed++;
    }

    static int shapesCount(){
    int shapesAlive = shapesCreated - shapesDestroyed;
    return shapesAlive;

    }

    int id(){
    return shapeID;
    }
};



class Rectangle: public Shape{

    private:
    double x1,y1,x2,y2; //co-ordinates of opposite corners

    public:

    Rectangle(double a,double b,double c,double x_1,double y_1,double x_2,double y_2):Shape(a,b,c){
    x1 = x_1;
    x2 = x_2;
    y1 = y_1;
    y2 = y_2;
    }

    string info(){
    //needs to return the coord's & colour AND SHAPE ID

        string rectInfo = toString();
        rectInfo += "\nThe co-ordinates of the rectangle's opposite corners are (";
        ostringstream convertX1;
        convertX1 << x1;
        rectInfo += ",";
        ostringstream convertY1;
        convertY1 << y1;
        rectInfo += ") and (";
        ostringstream convertX2;
        convertX2 << x2;
        rectInfo += ",";
        ostringstream convertY2;
        convertY2 << y2;
        rectInfo += ")\nThe Shape ID is: \a";
        ostringstream convertID;
        convertID << shapeID;
    return rectInfo;
    }

};

class Circle: public Shape{

    private:
    double x1,y1,radius; //all relevant coords for circle

    public:

    Circle(double a,double b,double c,double x_1,double y_1,double rad):Shape(a,b,c){
    x1 = x_1;
    y1 = y_1;
    radius = rad;
    cout << "test";
    }

    string info(){
    string circInfo = toString();
    circInfo += "\nThe co-ordinates of the circles center is (";
    ostringstream convertX1;
    convertX1 << x1;
    circInfo += ",";
    ostringstream convertY1;
    convertY1 << y1;
    circInfo += ")\nThe radius of the circle is: ";
    ostringstream convertRadius;
    convertRadius << radius;
    circInfo += "\nThe Shape ID is: \a";
    ostringstream convertID;
    convertID << shapeID;
    return circInfo;
    }
};


int main()
{
Circle c1(1,1,1,1,1,1);
return 0;
}

Problem:

Trying to create either a Rectangle or Circle object from my derived shape classes. The question requires that the shapesDestroyed and Created variables be private data members within the Shape class. However, trying to access these in my derived class constructors is proving an issue. Basically they are to increment as a shape is created and as one is destroyed. However, it is running into an issue with the created and destroyed variables from my class. I have tried changing these to protected (the question states private though) to no avail. Any help would be greatly appreciated in trying to get this to run correctly.

Justin
  • 24,288
  • 12
  • 92
  • 142
bkell
  • 1
  • 1

1 Answers1

0

Your static variables as class members need to be initialized outside of the class like this:

int Shape::shapesCreated = 0;

Do that in a .cpp file.

I think even you can do it directly inside class for ints but I the above should work.

Germán Diago
  • 7,473
  • 1
  • 36
  • 59
  • I can only have one file? Will this still work? – bkell Mar 15 '18 at 17:57
  • if it is the file you compile, yes, add it outside of the class for each static variable. – Germán Diago Mar 15 '18 at 17:58
  • Defining inside the class works for `const static`, not for just `static`. – Bo Persson Mar 15 '18 at 17:58
  • Outside of the class I added: static Shape::shapesCreated = 0; static Shape::shapesDestroyed = 0; And removed my function which I was using to initialize them previously. Now my error message reads: "int shape::shapesDestroyed is private" on the line where its first declared in the class. And also: shapeDestroyed in class Shape does not name a type. Any advice? – bkell Mar 15 '18 at 18:01
  • Not a new question, but the solution provided doesn't appear to work :( – bkell Mar 15 '18 at 18:20
  • I corrected the reply, my bad. You do not need the static outside when defining the variable, only in the class. That should work @bkell – Germán Diago Mar 15 '18 at 19:36