## pash101

I am writing a project to calculate the area and volume of 2d and 3d shapes. I have a class hierarchy with my abstract base class called 'shape'. I want to make a separate class to calculate a prism of a specified depth from any 2d shape, yet am unsure how to do this.

Any help will be greatly appreciated.

This example is for a circle, yet I want to be able to do this for all 2d shapes.

(Relevant code)

``````template <class prism> class prism
{
private:
double depth;

public:
prism(){depth=0;}//default constructor
prism(double depth1, shape* sha): shape(area){depth=depth 2; area=sha.getarea();}

};``````

then in main

``````if (choice=='c')
{
double depth(0.);
a.push_back(new circle());
vector<shape*>::const_iterator it;
it = a.begin();
(*it)->info();

cout<<"Enter the depth for a prism"<<endl;
cin>>depth;

circle c(1);
prism <shape*> b(depth, c);

delete *it;
a.pop_back();
}``````

## Fbody 682

Hmmmm..... I have not done this before, so this will be a learning experience for both of us.

I know you'll want to create a "shape" class, as you have done. I also know you will then want to create shape-specific classes that inherit from "shape" for each shape you want to calculate the area of. Also, as you seem to have done.

``````class base {
};

class derive1_1 : public base {
};

class derive1_2 : public base {
};``````

This is where I might get lost:
Once you do that, you'll want to create a template class called "prism" that accepts any "shape" or "shape-derived" class.

From a strictly logical standpoint, I think you would want something like this:

``````template <class T> class derive2 : public T {
};``````

I don't know if this is legal though.

Assuming it is, when you create your prism you would use something like this:

``derive2<derive1_1> aGenericObject;``

Ultimately this would translate into something like:

``````class shape {
};

class circle : public shape {
};

class square : public shape {
};

template <class T> class prism : public T {
};

prism<circle> cylinder;
prism<square> rectangularPrism;``````

## pash101

Thanks for the help, I am able to access the prism class now using the method you suggested. However I've come across one other problem I didn't realise I had. Again using my derived circle class to illustrate, I want to save the area calculated into a vector so it can be accessed by other functions, and ultimately by the prism class.

``````class circle : public twodshape
{
private:
int num_vertices;
vector <double> x;

public:

circle(){num_vertices=0;}//default constructor
circle(int numv)  {num_vertices=numv;

x.push_back(2);
cout<<x.size()<<endl;

cin>>x[0];
area=PI*x[0]*x[0];
x[1]=area;

}//paramatised constructor

~circle(){}

double get_numv() const {return num_vertices;}
double setvalues(int a);
double get_area() const{return x[1];}

void info(){
cout<<"The area of this this circle is "<<x[1]<<endl;
};

};``````

(N.B. my variable Num_Vertices is left over from my square class, I realise circles do not have vertices.)

## Fbody 682

``x.push_back(2);``

Based on your intent, this is not correct. When you do a push_back(), you push the value of the argument into the vector as the last element. The surrounding context in your code makes it look like you are trying to use this to set the size of the vector.

Instead, try creating a vector<double> in main(). You would then iterate through your objects and push the result of the area() method for each one into the vector.

``````vector<double> myDoubleVector;

for(int i = 0; i < count; i++) {
myDoubleVector.push_back(anotherFunctionWithDoubleReturnValue());
}``````

## pash101

I like the idea of storing areas in a vector in main, however I think something may be wrong with my access function for area, or the way I am implementing it.

The output I get from this will output the correct area the first time when I calculate it in my constructor, however, in main and in the header void function the area is returned as 0 both times. Is there a way of storing it's value once it has been initially calculated in the constructor?

Thanks

``````class circle : public twodshape
{
private:
int num_vertices;
int count;
vector <double> x;

public:

circle(){num_vertices=count=0;}//default constructor
circle(int numv, int cnt)  {num_vertices=numv; count=cnt;

//cout<<"entered constructor "<<count<<endl;
x.resize(2);
cin>>x[0];
area=PI*x[0]*x[0];
x[1]=area;

cout<<x[1]<<endl;

}//paramatised constructor

~circle(){}

double get_numv() const {return num_vertices;}
double setvalues(int a);
double get_area() const{return area;}

void info(){
cout<<"entered info"<<endl;
cout<<"The area of this this circle is "<<get_area()<<endl;
};

};``````

and then in main

``````if (choice=='c')
{
double depth(0.);
a.push_back(new circle());
//cout<<a[0]<<endl;
circle(1, 1);
for (vector<shape*>::const_iterator it = a.begin(); it != a.end(); ++it) {
(*it)->info();

vector<double> mydouble;
mydouble.push_back((*it)->get_area());

cout<<mydouble[0]<<endl;

double z = (*it)->get_area();
cout<<"area 2 "<<z<<endl;

delete *it;
}``````

## mitrmkar 1,056

You don't want to have the vector ( `mydouble` ) declared inside the for-loop, because that gives you a fresh re-constructed vector on every iteration of the loop. So declare the vector in another scope, outside the loop.

## pash101

Thanks for the help so far, I've moved the vector(my double) out to above the for-loop. The output I get when running the program and selecting circle is as follows:

"
//in constructor
3
28.2743
//in info
entered info
the area of this circle is 0
//In main
0
area 2 0
Enter the depth for a prism

etc...."

I'm still unsure how to get my double get_area() to sucesfully return the area. I realise I could re-calculate the area each time by having a 'cin' entering the necessary values, however this is a bit of a clunky way of doing it.

## pash101

Sorry to bump, but does anyone have any suggestions?

## mitrmkar 1,056

You might post the current code and point out the current problems.

## Fbody 682

Your shape-derived classes should store shape-specific information within their protected: sections. For example, circle should store a double called radius, square should store doubles called length and width. Then your get_area() methods would use a shape-specific equation to calculate the area. For example circle::get_area() would return a double that is the result of PI*radius^2 and square::get_area() would return a double that is the result of length * width. You would then store the return values into a vector<double>.

You would then do something similar with the prism template. The prism<T> class would have a private/protected double data member called depth and a public member called get_volume(). When called, the prism<T>::get_volume() method would subsequently call the T::get_area() method, then multiply that return value by the depth member.

To store the return values in the vector, you would declare the vector outside your loop, then push the return value(s) into the vector inside the loop.

Convert this into a loop and you should be on the right track:

``````prism<circle> cylinder;
vector<double> volumes;

volumes.push_back(cylinder.get_volume());``````

You would have a similar sequence for areas, except you wouldn't use prism<T>, you would use a specific shape:

``````circle aCircObj;
vector<double> areas;

areas.push_back(aCircObj.get_area());``````

## pash101

Thanks again for the help so far, my (hopefully) last question (again using circle as an example), when i call: prism<circle> cylinder;, how will it know to use the area previously inputted in a.push_back(new circle(radius));

My code:

Main

``````if (choice=='c')
{

for (vector<shape*>::const_iterator it = a.begin(); it != a.end(); ++it) {

shapeareas.push_back((*it)->get_area());
//(*it)->info();
cout<<shapeareas[0]<<endl;

double depth(0.);
cout<<"Enter the depth of the prism"<<endl;
cin>>depth;
prism <circle> cylinder(depth);
shapevolumes.push_back(cylinder.get_volume());
cout<<shapevolumes[0]<<endl;
delete *it;
}``````

``````class circle : public twodshape
{
private:

public:

}

~circle(){}

double get_area()
{

return area;
}

void info(){
cout<<"entered info"<<endl;
cout<<"The area of this this circle is "<<get_area()<<endl;
};
//
//
//
//
//
//
template <class p> class prism : public p
{
private:
double depth;

public:
prism(){depth=0;}//default constructor
prism(double depth1) {depth=depth1;
cout<<"entered prism"<<endl;
}

double get_volume(){
//cout<<"Enter the depth"<<endl;
//cin>>depth;
area=get_area();
double volume=area*depth;
cout<<"volume is "<<volume<<endl;

return volume;

}
};``````

This outputs the volume as 0.

## Fbody 682

Hmmmm....... that would be hard to do because the current arrangement creates separate instances of the 2-dimensional shapes, 1 independent instance and 1 instance inside the prism object. I'll have to think on that more...

## Fbody 682

I think you'll want to eliminate creation of the 2-D shapes from the main code altogether and go straight to the prism<p> objects. The classes for the 2-D shapes would still exist and be utilized, but not directly within your main code.

Since prism<p> inherits from class p (where p = anyTwoDimensionalShape), and p inherits from abstractShape, prism<p>'s public interface contains not only its own methods but those of the inherited class(es) public interfaces as well (assuming public inheritance was specified). As a result, a prism<p> object would have a get_area() method appropriate for the 2-D shape specified by p.

This should work. With the added benefit of having fewer objects to keep track of.

``````int main() {
vector<shape*> myShapes;  //create a vector of prism<p> pointers
/* push some shapes into the vector
i.e. myShapes.push_back(new prism<aShape>) */
vector<double> crossSectionalAreas, prismVolumes; //create the data arrays

/* manipulate the prism(s) */

for (vector<prism<shape*>>::const_iterator it = myShapes.begin(); it != myShapes.end(); ++it) {
crossSectionalAreas.push_back(it->get_area()); //get the cross-sectional area
prismVolumes.push_back(it->get_volume());  //get the prism's volume
}

/* other functionality */

//release the shapes / call the shape destructors
myShapes.clear();

return 0;
}``````

## Fbody 682

Ran out of edit time, I just realized that there is a goof related to the iterator object(s) in the code above, it won't work as shown, but it should give you the basic idea.

Eh,... who am I kidding? I can't leave it hanging like that...
Should be more like this:

``````int main() {
vector<shape*> myShapes;  //create a vector of shape pointers
/* push some prism shapes into the vector
i.e. myShapes.push_back(new prism<aShape>) */
vector<double> crossSectionalAreas, prismVolumes; //create the data arrays

/* manipulate the prism(s) */

for (vector<shape*>::const_iterator it = myShapes.begin(); it != myShapes.end(); ++it) {
crossSectionalAreas.push_back(it->get_area()); //get the cross-sectional area
prismVolumes.push_back(it->get_volume());  //get the prism's volume
}

/* other functionality */

//release the shapes / call the shape destructors
myShapes.clear();

return 0;
}``````

## pash101

That should work, do you suggest I transfer reading the data into the header file get_area() functions themselves, rather than adding data into the constructor?

``````class circle : public twodshape
{
private:

public:

}

~circle(){}

double get_area()
{
return area;
}
};``````

have,

``````private:

public:

}

~circle(){}

double get_area()
{
cin>>area;
return area;
}
};``````

## Fbody 682

No, the radius should be a permanent, yet modifiable, part of the circle's properties. It should be entered as part of the object creation, if not before. Something like the first version would be better. Otherwise, you just have a plain ol' function and eliminate the point of having the object in the first place.

i.e.

``````double radius;

That way, the radius is part of the circle's properties. Then, get_area() would just reference the circle's radius property and return the result of the equation.

## pash101

``myShapes.push_back(new prism<circle>(radius))``

doesn't seem to put the radius into my constructor. This means I can't get the cross sectional area out nor the volume of the prism.

Once again, thanks for the help, I can see it's close......

## Fbody 682

You will need to use overloaded constructors with initialization lists (the link may pop up a modal, just close it):

``````class base1 {
protected:
double base1Priv1;
public:
base1(double newPriv1 = 0.0, double dummyArg = 0.0)
: base1Priv1(newPriv1) {}
//overloaded constructor that can function as default constructor
};

class base2 {
protected:
double base2Priv1, base2Priv2;
public:
base2(double newPriv1 = 0.0, double newPriv2 = 0.0)
: base2Priv1(newPriv1), base2Priv2(newPriv2) {}
//overloaded constructor that can function as default constructor
};

template <class T> class tempDerived : public T {
public:
tempDerived() { }  //default constructor
: T(newB1P1) {}
tempDerived(double newB2P1, double newB2P2) //overloaded constructor
: T(newB2P1, newB2P2) {}
};``````

This example has a huge bug where a non-existant base-class constructor could be called. I'm not sure how to correct it ATM, but it should give you the basic idea.

I added dummyArg to the base1 constructor as a cheap workaround, it's really not the best solution though. I'll think on it more...

## Fbody 682

Actually, the more I think about it, the more I think the "buggy" version is better. That way, if someone attempts to build an object based on the base1 class incorrectly, it will cause an error of some sort, most likely a linker error.

As a designer, I would consider this a desirable outcome. That way, I help ensure that the class is being used correctly.

## pash101

I've modified my circle and template classes to the following:

``````class circle : public twodshape
{
private:

public:

}
~circle(){}

double get_area()
{
return area;
}

};

//
//
//
//
//
//
template <class p> class prism : public p
{
private:
double depth;

public:

prism(){}//default constructor
prism(double IN)
: p(IN){}

prism(double IN1, double IN2)
: p(IN1, IN2){}

double get_volume(){
cout<<"Enter the depth"<<endl;
cin>>depth;
area=get_area();
double volume=area*depth;
return volume;
}
};``````

In main I've modified it to

``````if (choice=='c')
{

vector<double> crossSectionalAreas, prismVolumes;

for (vector<shape*>::const_iterator it = a.begin(); it != a.end(); ++it) {

crossSectionalAreas.push_back((*it)->get_area());
//(*it)->info();
cout<<"111 "<<crossSectionalAreas[0]<<endl;

double depth(0.);
prismVolumes.push_back(cylinder.get_volume());
cout<<prismVolumes[0]<<endl;
delete *it;
}

}``````

This now correctly outputs both the area and the volume! Does it look like I have made any mistakes with the initialization lists?

## Fbody 682

You really need to stop cut/pasting my examples. I'm specifically writing them in a way that isn't directly compatible with your code for a reason.