I have class Set which consists of dynamically allocated IShape where IShape is inherited by Square, Rectangle etc. and I need to make filter function to create new set of only certain type (E.g. Squares). Basically to go through existing set and pick only shape which is defined somehow (through parameters?) and create new set of that shape. How could this be done?
To avoid using dynamic_cast, have your IShape class declare a pure virtual function called (say) GetTypeOfShape. Then override that in each of your derived classes to return the type of shape that each represents (as an enum, say). Then you can test that in your filter function and proceed accordingly.
Example code:
#include <iostream>
class IShape
{
public:
enum class TypeOfShape { Square, Rectangle /* ... */ };
public:
virtual TypeOfShape GetTypeOfShape () = 0;
};
class Square : public IShape
{
public:
TypeOfShape GetTypeOfShape () override { return TypeOfShape::Square; }
};
class Rectangle : public IShape
{
public:
TypeOfShape GetTypeOfShape () override { return TypeOfShape::Rectangle; }
};
// ...
int main ()
{
Square s;
Rectangle r;
std::cout << "Type of s is: " << (int) s.GetTypeOfShape () << "\n";
std::cout << "Type of r is: " << (int) r.GetTypeOfShape () << "\n";
}
Output:
Type of s is: 0
Type of r is: 1
Live demo
Related
I'm trying to implement a menu for my Shape program. I've implemented all of the shapes classes. Two are deriving straight from the abstract class "Shape", and two others are deriving from a class called "Polygon" which derives from "Shape" as shown bellow:
Shape -> Polygon -> Rectangle, Triangle
`-> Circle, Arrow
In my menu class, I want to create some sort of an array that can contain the pointers to the objects and with the type of the base class "Shape". But I'm not sure how to do it properly and in a way which will work for all of my shapes, because 2 of my classes aren't deriving from "Shape" directly.
This is my menu class:
class Menu
{
protected:
//array of derived objects
public:
Menu();
~Menu();
// more functions..
void addShape(Shape& shape);
void deleteAllShapes();
void deleteShape(Shape& shape);
void printDetails(Shape& shape);
private:
Canvas _canvas; //Ignore, I use this program to eventually draw this objects to a cool GUI
};
And in the function "addShape(Shape& shape);", Which I want to use to add each given shape to my array. How can I implement the addition of new objects to it? And also, how can I check if the given object is deriving from "Polygon" or not? Because if so then I need to call the member functions differently as far as I understand.
I see that you have an array in Menu, let's say:
Shape* myshapes[10];
The shapes can be Rectangles, Triangles, Circles etc.
What you want is to be able to use the Menu's printDetails() method like this:
void printDetails()
{
for(int i = 0; i < size; i++)
{
cout << "Index " << i << " has " << myshapes[i]->getShapeName() << endl;
}
}
The getShapeName() will return a string, e.g. "Rectangle" if it is Rectangle.
You will be able to do this with the help of pure virtual function. The pure virtual function must be in the abstract class Shape, which has:
virtual string getShapeName() = 0; //pure virtual
It means that we are expecting a definition for this function in the derived class. This way you will be able to use getShapeName() method using the Shape pointers in the shapes array, which will tell you whether the shape is Rectangle, Triangle, or Circle etc.
class Shape
{
public:
virtual string getShapeName() = 0;
};
class Circle : public Shape
{
private:
int radius;
public:
Circle(int r) { radius = r; cout << "Circle created!\n"; }
string getShapeName() { return "Circle"; }
};
class Arrow : public Shape
{
private:
int length;
public:
Arrow(int l) { length = l; cout << "Arrow created!\n"; }
string getShapeName() { return "Arrow"; }
};
class Polygon : public Shape
{
public:
virtual string getShapeName() = 0;
};
class Triangle : public Polygon
{
private:
int x, y, z;
public:
Triangle(int a, int b, int c) { x = a; y = b; z = c; cout << "Triangle created!\n"; }
string getShapeName() { return "Triangle"; }
};
class Rectangle : public Polygon
{
private:
int length;
int width;
public:
Rectangle(int l, int w){ length = l; width = w; cout << "Rectangle created!\n"; }
string getShapeName() { return "Rectangle"; }
};
To implement the addShape() method you can do this:
void addShape(Shape &shape)
{
myshapes[count] = &shape;
count++;
}
Also, keep in mind to pass the Shape by reference or by using pointer, in the addShape() method.
I hope this helps... Best of luck :-)
How to resolve not a member of base class when create derived object using new operator
When i execute the below program, i am getting the below error only when i create a object using new operator "shape *s=new Rectangle";. But i havent faced any issues when i create object "Rectangle s"
Actually i dont want to use hello method in my Triangle class. Need to acces/uses hello method in rectangle class by creating object using new operator "shape *s=new Rectangle".
Please let us know how to resolve this issue using new operator.
Error:
1>c:\shape\shape\shape.cpp(60) : error C2039: 'hello' : is not a member of 'Shape'
1>c:\shape\shape\shape.cpp(10) : see declaration of 'Shape'
Code snippet:
// Shape.cpp : Defines the entry point for the console application.
//
#include <iostream>
using namespace std;
// Base class
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// Derived classes
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
void hello()
{
std:cout<<std::endl<<"hello"<<std::endl;
}
};
class Triangle: public Shape
{
public:
int getArea()
{
return (width * height)/2;
}
};
int main(void)
{
Shape *s= new Rectangle;
// Triangle Tri;
s->setWidth(5);
s->setHeight(7);
// Print the area of the object.
cout << "Total Rectangle area: " << s->getArea() << endl;
s->hello();
/*
Tri.setWidth(5);
Tri.setHeight(7);
// Print the area of the object.
cout << "Total Triangle area: " << Tri.getArea() << endl;
*/
return 0;
}
You have a pointer to Shape, but (and this is what your compiler tells you) Shape has no member hello().
So theres two ways to access it:
Either you cast it to Rectangle* first (which might fail for non-rectangles) or you create a function virtual void hello() in Shape which is then resolved at compile-time - for all classes that inherit from Shape.
I have a simple Shape factory example where I can create Circles or Squares.
I have added an extra "contents" attribute to the Circle class that is not part of the Square derived class or the Shape base class.
The problem is, when I create an instance of the Circle class using my factory, I am unable to modify the contents of the created object.
#include <iostream>
using namespace std;
// Shape base clas
class Shape {
public:
// Shape constructor;
Shape() {
id_ = total_++;
}
// Virtual draw method
virtual void draw() = 0;
protected:
int id_;
static int total_;
};
int Shape::total_ = 0;
// Circle derived class
class Circle : public Shape {
public:
void draw() {
contents = 0;
cout << "circle " << id_ << ": draw, contents: " << contents << endl;
}
// Attribute to attempt to access
int contents;
};
// Square derived class
class Square : public Shape {
public:
void draw() {
cout << "square " << id_ << ": draw" << endl;
}
};
// Factory class
class Factory {
public:
Shape* createCurvedInstance() {
return new Circle;
}
Shape* createStraightInstance() {
return new Square;
}
};
// Main
int main()
{
Factory* factory = new Factory;
Shape* thing = factory->createCurvedInstance();
// Draw method works fine (as it should)
thing->draw();
// Fails: "expression must have class type"
thing.contents = 4;
system("pause");
return 0;
}
How can I access attributes of the derived class when I create an instance of it using a factory?
No way unless you cast, and Thou Shall Not Cast. The whole idea behind polymorphic is instances that they make themselves available through immutable interface. They highlihgt an IS-A replationship, where Circle is a Shape for all intents and purposes, except implementation details, which no one is interested in. If you add publically 'contents' to your Circle, it is no longer a Shape, so it should not be constructed through factory.
Since a Shape has no content, you cannot modify the content from a pointer to Shape. full stop.
However, if you know that your particular Shape is in fact a Circle and has content, you can cast to a pointer to Circle.
void set_content(Shape*shape, int content)
{
auto circle = dynamic_cast<Circle*>(shape);
if(circle)
circle->content = content;
}
This version is extra safe: it does not assume that shape is a Circle*, but uses dynamic_cast<Circle*>, which will return non-null only if shape is in fact a Circle*.
The dynamic_cast<> comes with some costs, which you may want to avoid. If you have any other fool proof way to establish that your shape is in fact a Circle, you can use a simple static_cast<>:
class Shape
{
public:
virtual bool has_content() const { return false; }
// ...
};
class ShapeWithContent : public Shape
{
public:
bool has_content() const override { return true; }
int content = 0;
};
class Circle : public ShapeWithContent
{
// ...
};
void set_content(Shape*shape, int content)
{
if(shape->has_content())
static_cast<ShapeWithContent*>(shape)->content = content;
}
Having said all that, I like to emphasize that you should try to design your code in a way that makes such tricks redundant/unnecessary.
It turns out I didn't want a factory at all!
What I really wanted was some sort of container class to hold different types of shapes. Neither shape is derived from the ShapeContainer class but both shapes can be accessed through it.
#include <iostream>
using namespace std;
// Circle class
class Circle {
public:
Circle() {
contents = 2;
}
void draw() {
cout << "circle " << contents << endl;
}
int contents;
};
// Square class
class Square {
public:
void draw() {
cout << "square" << endl;
}
};
// Shape containter class
class ShapeContainer {
public:
Circle* getCircle() {
return new Circle;
}
Square* getSquare() {
return new Square;
};
};
// Main
int main()
{
ShapeContainer* container = new ShapeContainer;
Circle* circle = container->getCircle();
circle->draw();
circle->contents = 42;
circle->draw();
system("pause");
return 0;
}
This allows me to make both Circles and Squares while still being able to access the contents of the Circle object!
Sometimes you need to look at things from a whole new perspective to get the functionality you really want...
I'm confused...it seems that both things do the same thing.
In this first code, I believe that the derived classes are hiding the function names of the base classes.
#include <iostream>
using namespace std;
class Quadrilateral {
public:
void greeting() {
std::cout << "i am a quadrilateral" << std::endl;
}
};
class Square : public Quadrilateral {
public:
void greeting() {
std::cout << "i am a square" << std::endl;
}
};
class Trapezoid : public Quadrilateral {
public:
void greeting() { //hides greeting from quadrilateral function
std::cout << "Hi I'm a Trapezoid" << std::endl;
}
};
int main()
{
Trapezoid tz;
tz.greeting();
}
This seems to have the same exact result: [here they are being overriden because it is virtual in the base class]
#include <iostream>
using namespace std;
class Quadrilateral {
public:
virtual void greeting() {
std::cout << "i am a quadrilateral" << std::endl;
}
};
class Square : public Quadrilateral {
public:
void greeting() {
std::cout << "i am a square" << std::endl;
}
};
class Trapezoid : public Quadrilateral {
public:
void greeting() { //hides greeting from quadrilateral function
std::cout << "Hi I'm a Trapezoid" << std::endl;
}
};
int main()
{
Trapezoid tz;
tz.greeting();
}
So I guess I'm just really confused as to...what is the difference? Or what is the point of making it virtual in the base class if it's just gonna have the same effect in this situation?
Virtual functions are used to call the overriden function from the base class pointer.
With your second example you can get the same result if you do the following in the main()
Trapezoid tz;
Quadrilateral *base = &tz;
base->greeting(); // it will print "Hi I'm a Trapezoid"
And this is the difference with the first example: possibility to call derived function from the base class pointer.
If you not override the virtual base function in the derived class, then the base virtual function will be called.
Usage example.
Imagine, that you want to create many objects with the base class Quadrilateral (for example five squares and three trapezoids):
Square sq1, sq2, sq3, sq4, sq5;
Trapezoid tz1, tz2, tz3;
Now, at some point in your code you want to go throw all of this objects and call the abstract function (in your case greeting()). So, with help of virtual function you can do it very simple: put all objects in an array of pointers and call the propper function. Here is how:
Quadrilateral *base[8] = {&sq1, &sq2, &sq3, &sq4, &sq5, &tz1, &tz2, &tz3};
for (int i = 0; i < 8; i++) {
base[i]->greeting();
}
In the output you will recieve five times "i am a square" and three times "Hi I'm a Trapezoid".
It comes vary helpfully when you create all different shapes (for example with different dimensions, properties) and want to go throw all of this objects and call, for example, calc() function to make an calculation individualy for each shape.
I hope this helps you.
In C++, if you declare/have a struct or class variable like in this example, the compiler trivially knows its type and always calls the correct function, irrespective of virtual/not.
Virtual functions only matter when dealing with pointers or references.
Try adding this after you existing code, before the end of main:
Quadrliateral *q = &t;
q->greeting();
And you will find it matters a lot whether all the greetings functions are virtual or not.
First of all, format your code please!
First example
class Quadrilateral {
public:
void greeting() {
std::cout << "i am a quadrilateral" << std::endl;
}
};
class Square : public Quadrilateral {
void greeting() {
std::cout << "i am a square" << std::endl;
}
};
class Trapezoid : public Quadrilateral {
public:
void greeting() { //hides greeting from quadrilateral function
std::cout << "Hi I'm a Trapezoid" << std::endl;
}
};
int main() {
Trapezoid tz;
tz.greeting();
}
In this example is totally normal that Trapezoid.greeting() hides Quadrilateral.greeting(): it's an overriding (same method name, same return, same parameters (none)).
Second example
class Quadrilateral {
public:
virtual void greeting() {
std::cout << "i am a quadrilateral" << std::endl;
}
};
class Square : public Quadrilateral {
void greeting() {
std::cout << "i am a square" << std::endl;
}
};
class Trapezoid : public Quadrilateral {
public:
void greeting() { //hides greeting from quadrilateral function
std::cout << "Hi I'm a Trapezoid" << std::endl;
}
};
int main() {
Trapezoid tz;
tz.greeting();
}
The same. You create an objcet of static-type Trapezoid that have dynamic-type Trapezoid. So tz.greeting will print "I'm a trapezoid" because greeting() is an override.
Third example
class Shape {
public:
virtual void greeting() {
std::cout << "Shape" << std::endl;
}
};
class Square : public Shape {
/* override method greeting() of Shape class */
void greeting() {
std::cout << "Square" << std::endl;
}
};
class Triangle : public Shape {
public:
/* override method greeting() of Shape class */
void greeting() {
std::cout << "Triangle" << std::endl;
}
};
int main() {
Shape* shape = new Triangle();
shape->greeting(); /* prints "Triangle" */
shape = new Square();
shape->greeting(); /* prints "Square" */
}
class Material
{
public:
void foo()
{
cout << "Class Material";
}
};
class Unusual_Material : public Material
{
public:
void foo()
{
cout << "Class Unusual_Material";
}
};
int main()
{
Material strange = Unusual_Material();
strange.foo(); //outputs "Class Material"
return 0;
}
I would like for this to result in the "Class Unusual_Material" being displayed to the console. Is there a way I can achieve this? In my program I have a class Material from which other more specific materials are derived. The method Material::foo() represents a method in Material that is adequate for most materials, but occationally, another foo() needs to be defined for a material with unusual properties.
All objects in my program contain a Material field. In the event that they are assigned an unusual material, I would like the derived, unusual foo to be called.
This is probably either pretty easy, or impossible, but I can't figure it out either way.
Thanks
What you want is polymorphism, and to enable it for a function you need to make it virtual:
class Material
{
public:
virtual void foo() // Note virtual keyword!
{
cout << "Class Material";
}
};
class Unusual_Material : public Material
{
public:
void foo() // Will override foo() in the base class
{
cout << "Class Unusual_Material";
}
};
Also, polymorphism only works for references and pointers:
int main()
{
Unusual_Material unusualMaterial;
Material& strange = unusualMaterial;
strange.foo();
return 0;
}
/* OR */
int main()
{
Unusual_Material unusualMaterial;
Material* strange = &unusualMaterial;
strange->foo();
return 0;
}
What you have in your code snippet will slice the Unusual_Material object:
int main()
{
// Unusual_Material object will be sliced!
Material strange = Unusual_Material();
strange.foo();
return 0;
}
Still better explanation would be..
class Base
{
public:
void foo() //make virtual void foo(),have derived method invoked
{
cout << "Class Base";
}
};
class Derived: public Base
{
public:
void foo()
{
cout << "Class Derived";
}
};
int main()
{
Base base1 = Derived ();
Base1.foo(); //outputs "Class Base"
// Base object, calling base method
Base *base2 = new Derived ();
Base2->foo(); //outputs"Class Base",Again Base object calling base method
// But to have base object, calling Derived method, following are the ways
// Add virtual access modifier for base foo() method. Then do as below, to //have derived method being invoked.
//
// Base *base2 = new Derived ();
// Base2->foo(); //outputs "Class Derived" .
return 0;
}