So I saw this thread: What does it mean to "program to an interface"?. Which talks about declaring a Parent, but initializing it as a Child. Is it possible to do the same but with c++? For example: I have an interface Shape which can be implemented as Triangle or Square.
I tried to do the following but my program didn't compile:
Shape * myShape = new Square();
myShape->uniquetoSquare();
"typeinfo for Shape", referenced from:
typeinfo for Triangle in Triangle.o
class Shape {
public:
Shape(){};
int height;
int width;
string color;
void sayHello(){
cout << "Hello!";
}
int getArea(){
return 0;
}
}
class Triangle: public Shape {
public:
bool obtuse;
Triangle(){
obtuse = false;
};
void sayHello(){
cout << "Hello I'm a triangle!";
}
int getArea(){
return height*width / 2;
}
}
class Square: public Shape {
public:
bool rectangular
Square(){
rectangle = true;
};
void sayHello(){
cout << "Hello I'm a square!";
}
int getArea(){
return height*width;
}
void uniqueToSquare(){
cout << "This func is only in square!";
}
}
Shape does not have a function named uniqueToSquare. Remember that if you are using a Shape, then you can only use shape-like methods.
If you want to use it as a Square, then do something like:
Square* mySquare = dynamic_cast<Square*>(myShape);
if (mySquare != nullptr) mySquare->uniqueToSquare();
This is a simple polymorphism example. Yes it is possible in C++ and is actually the heart of the benefits of Object-Oriented design
With C++ it isn't as simple as you might hope. You need virtual functions to do what you want. Modifying your example to be "good" C++.
class Shape {
public:
Shape(){}
int height;
int width;
string color;
virtual void sayHello() const {
cout << "Hello!";
}
virtual int getArea() const {
return 0;
}
//virtual destructor, no need to declare this on the derived types
virtual ~Shape() {}
}
class Triangle : public Shape {
public:
bool obtuse;
Triangle() {
obtuse = false;
}
void sayHello() const {
cout << "Hello I'm a triangle!";
}
int getArea() const {
return height*width / 2;
}
}
class Rectangle : public Shape {
public:
bool square;
Rectangle() {
square = false;
}
void sayHello() const {
cout << "Hello I'm a rectangle!";
}
int getArea() const {
return height*width;
}
void uniqueToRectangle() const {
cout << "This func is only in rectangle!";
}
}
The error your getting seems to be because of missing runtime type information RTTI. You may want to enable this but it really is unnecessary for what you want to achieve. Use dynamic cast as others have suggested (which also uses RTTI).
Shape* myShape = new Rectangle();
((Rectangle*)myShape)->uniquetoRectangle();
This is OK but remember to delete myShape; before it goes out of scope. See RAII for the use of destructors for that.
Your variable myShape is a pointer to a Shape. Your class Shape does not have a method called uniqueToSquare(). Therefore, you have an error.
The solution is to initialise myShape as a Square simply by Square myShape = Square();
Remember that it is always better to preserve the real type of an object, this is better for performance, and basically gives more information to the compiler. You only resort to dynamic polymorphism when you really have to (ie, storing polymorphic objects in an array).
Related
Consider the following code
class Shape
{
protected:
int length, height;
public:
Shape();
~Shape();
};
class Square : Shape
{
private:
double Area;
public:
Square();
~Square();
};
class Circle : Shape
{
private:
double Circumference;
public:
Circle();
~Circle();
};
int main()
{
Shape *shape[5];
int choice, i = 0;
cout << "Which shape are you making?\n";
cout << "1. Square\n";
cout << "2. Circle\n";
cin >> choice;
if (choice == 1)
{
shape[i] = new Square();
i++;
}
if (choice == 2)
{
shape[i] = new Circle();
i++;
}
}
How would I make an array of pointers that contain both Circle and Squares so I can easily access both later to do stuff with it? Currently, it is giving me an error in the shape[i] = new Square(); and shape[i] = new Circle(); in main() and I don't know how to create an array of pointers to inherited classes.
You need to specify what kind of inheritance you want; More specifically, you need to tell the compiler that it is a public inheritance, meaning, that your entire code-base can know that Circle and Square are Shape.
Just change the declaration of the classes into:
class Circle : public Shape
class Square : public Shape
Also, consider having Shape as a true virtual interface, meaning - it should have nothing other than the public API that each shape should have, for example:
class IShape
{
public:
virtual double get_area() const = 0;
virtual double get_perimeter() const = 0;
// and so on...
virtual ~IShape() = 0;
protected:
virtual double calculate_something() const = 0;
// also protected can be here
};
Also, notice that using raw arrays, and especially raw arrays of raw pointers, such as:
Shape *shape[5];
is a good way to cause memory leak in your program; You should use both std::array and std::unique_ptr<IShape> in this context, meaning, your main should look like:
std::array<std::unique_ptr<IShape>, 5> shape;
int choice = 1;
int i = 0;
if (choice == 1)
{
shape[i] = std::unique_ptr<IShape>(new Square());
i++;
}
if (choice == 2)
{
shape[i] = std::unique_ptr<IShape>(new Circle());
i++;
}
It is because you are specifying the inheritance without telling whether it is public, private or protected . By default c++ will consider it private so you are not allowed to access a private class . change the inheritance from private to public and you are good to go .
something like this
class Square :public Shape
{
private:
double Area;
public:
Square();
~Square();
};
class Circle :public Shape
{
private:
double Circumference;
public:
Circle();
~Circle();
};
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 :-)
The function "foo" is from external library (In my case DEAlII ).
It takes in class type as template parameter and its object. It then creates a copy of this object and performs some operation on this object.
The problem is when the input class is polymorphic (template ). Then I always pass base class object but pointing to different derived class, but the copied object in the function "foo" will be base class.
And any call to member function on this copied object will call base class member function(But I need them to call to corresponding derived class member function).
Additionally the type of derived class is decided at runtime based on some input parameter. I cannot change/ move to different library, but I should be able to modify the function "foo" in the library(preferably not but may be as a last resort).
#include <iostream>
#include <memory>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0){
width = a;
height = b;
}
void set(int a){
width =a ;
}
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
virtual ~Shape()=default;
};
class Rectangle: public Shape {
public:
Rectangle( int a = 0, int b = 0):Shape(a, b) { }
int area () override{
cout << "Rectangle class area :" <<width*height <<endl;
return (width * height);
}
};
class Triangle: public Shape {
public:
Triangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
Triangle(const Triangle &triangle){
width = triangle.width;
height = triangle.height;
}
};
template <class temp>
void foo (temp &shape){
shape.area();
temp shape_sample = shape;
shape_sample.area();
}
// Main function for the program
int main() {
unique_ptr<Shape> shape;
Rectangle rec(10,7);
shape =make_unique<Rectangle> (rec);
foo (*shape.get());
shape->area();
return 0;
}
If the implementation of foo can't be change then I see two options here:
Option 1: Simply downcast to appropriate type if you know what it is:
foo(static_cast<Rectangle &>(*shape.get()));
Option 2 (overkill): hide the polymorphism using Bridge pattern:
class Shape {
protected:
class ShapeImpl {
public:
int width, height;
virtual ~ShapeImpl() = default;
// "virtual copy constructor" which you could've used without a Bridge
// if you could change "foo"
virtual ShapeImpl *clone() { return new ShapeImpl(*this); }
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
} *impl; // can't use unique_ptr because we want copy
Shape(ShapeImpl *impl)
: impl(impl) { }
public:
Shape(const Shape &other)
: impl(other.impl ? other.impl->clone() : nullptr) {
}
Shape(Shape &&other)
: impl(nullptr) {
std::swap(impl, other.impl);
}
virtual ~Shape() {
delete impl;
}
// copy-and-swap idiom with one assignment operator to "rule-of-five them all"
Shape &operator=(Shape other) {
std::swap(impl, other.impl);
return *this;
}
int area() {
return impl->area();
}
};
class Rectangle : public Shape {
protected:
class RectangleImpl : public ShapeImpl {
public:
ShapeImpl *clone() override { return new RectangleImpl(*this); }
int area() override {
cout << "Rectangle class area :" <<width*height <<endl;
return (width * height);
}
};
public:
Rectangle(int width = 0, int height = 0)
: Shape(new RectangleImpl())
{
impl->width = width;
impl->height = height;
}
};
If the implementation of the foo could not be changed. one other option is to write a wrapper around it and using dynamic cast send the right type to it.
template <class temp>
void foo (temp &shape)
{
shape.area();
temp shape_sample = shape;
shape_sample.area();
}
void fooWrapper(Shape* shape)
{
Rectangle* shape1 = dynamic_cast<Rectangle*>(shape);
if (shape1)
{
foo<Rectangle>(*shape1);
return;
}
Triangle* shape2 = dynamic_cast<Triangle*>(shape);
if(shape2)
{
foo<Triangle>(*shape2);
return;
}
shape->area();
return;
}
// Main function for the program
int main() {
unique_ptr<Shape> shape;
Triangle tri(10,7);
shape =make_unique<Triangle> (tri);
fooWrapper(shape.get());
Rectangle rec(10,7);
shape = make_unique<Rectangle> (rec);
fooWrapper(shape.get());
return 0;
}`
In this code I've started working on, I came across a common pattern that somehow doesn't sit right with me. Usually, it involves an enum, a map, a switch and some sort of class hierarchy. I've tried to abstract a MWE:
#include <iostream>
#include <map>
class Shape {
public:
virtual double SumOfInternalAngles() { throw std::exception(); }
};
class Triangle : public Shape {
public:
double SumOfInternalAngles() { return 180.0; }
};
class Rectangle : public Shape {
public:
double SumOfInternalAngles() { return 360.0; }
};
enum TeamShapes {AlicesTriangle, BobsRectangle, CarolsTriangle};
int main()
{
Triangle alicesTriangle;
Rectangle bobsRectangle;
Triangle carolsTriangle;
std::map<TeamShapes, Shape*> shapeMap;
shapeMap[TeamShapes::AlicesTriangle] = &alicesTriangle;
shapeMap[TeamShapes::BobsRectangle] = &bobsRectangle;
shapeMap[TeamShapes::CarolsTriangle] = &carolsTriangle;
for(auto it : shapeMap)
{
switch (it.first)
{
case TeamShapes::AlicesTriangle:
std::cout << it.second->SumOfInternalAngles() << std::endl;
break;
case TeamShapes::BobsRectangle:
std::cout << static_cast<Rectangle*>(it.second)->SumOfInternalAngles() << std::endl;
break;
}
}
return 0;
}
There seems to be repetitive information, and both versions of accessing the member function have drawbacks: In the first case, you need to have a virtual member function in the base class, which means that all the derived classes get "cluttered" with functions that don't really make sense for them, e.g. a Circle would end up with a function getCorners(). In the second case I would prefer not needing the cast, although I know that it is necessary. Maybe someone can point me in a direction where I can come up with a better design for this case.
I'm quite new to C++, so I'd like to hear what the "best practices" and "conventions" regarding such constructs are. Maybe the code is fine, and I simply need to adjust?
If you make your base class pure virtual (i.e make the class abstract), then you don't have to implement SumOfInternalAngles() in it and thus no need to throw an exception. Shape then becomes an abstract interface to be implemented by a derived class and this derived class MUST implement SumOfInternalAngles().
Then in your switch statement, you don't need to cast unless you wanted to call a method specific to the derived class such as getCorners() which may or may not be present in all derived versions of Shape.
To do this simply change you shape definition to
class Shape {
public:
virtual double SumOfInternalAngles() = 0;
};
And use the first version of your switch case.
i.e
case TeamShapes::AlicesTriangle:
std::cout << it.second->SumOfInternalAngles() << std::endl;
break;
case TeamShapes::BobsRectangle:
std::cout << it.second->SumOfInternalAngles() << std::endl;
break;
EDIT: some sample code to try and help illustrate.
#include <iostream>
#include <string>
class base
{
public:
virtual std::string AMethodThatMustBeImplemented() = 0;
virtual std::string ABaseMethod() { return std::string("base::ABaseMethod"); }
};
class A : public base
{
public:
virtual std::string AMethodThatMustBeImplemented() { return std::string("A::AMethodThatMustBeImplmented"); }
// No need to implment ABaseMethod here unless we wanted to!
};
class B : public base
{
public:
virtual std::string AMethodThatMustBeImplemented() { return std::string("B::AMethodThatMustBeImplmented"); }
virtual std::string ABaseMethod() { return std::string("B::ABaseMethod"); }
};
int main(int argc, char** argv)
{
//base obj; // can't do this since base has 'pure virtual' called AMethodThatMustBeImplemented.
A objA;
B objB;
std::cout << objA.AMethodThatMustBeImplemented() << '\n';
std::cout << objA.ABaseMethod() << '\n';
std::cout << objB.AMethodThatMustBeImplemented() << '\n';
std::cout << objB.ABaseMethod() << '\n';
base& b = static_cast<base&>(objB);
std::cout << b.ABaseMethod() << " <- notice still calling B::ABaseMethod\n";
std::cout << b.base::ABaseMethod() << " <- ah-ha now calling base::ABaseMethod\n";
}
Maybe what you want is an intermediate interface for your derived class, in this case a "Polygon" interface derived from "Shape", which has methods that make sense for polygons, but not for a circle for example :
#include <iostream>
#include <map>
#include <math.h>
class IShape {
public:
virtual double getArea() = 0;
};
class IPolygon : public IShape {
public:
virtual double sumOfInternalAngles() = 0;
};
class Triangle : public IPolygon {
public:
Triangle(double _base, double _height) : base(_base), height(_height) {}
double sumOfInternalAngles() { return 180.0; }
double getArea() { return (base * height)/2; }
private:
double base;
double height;
};
class Rectangle : public IPolygon {
public:
Rectangle(double _width, double _height) : width(_width), height(_height) {}
double sumOfInternalAngles() { return 360.0; }
double getArea() { return (width * height); }
public:
double width;
double height;
};
class Circle : public IShape {
public:
Circle(double _radius) : radius(_radius) {}
double getArea() { return (3.14 * pow(radius,3)); }
public:
double radius;
};
enum TeamShapes {AlicesTriangle, BobsRectangle, CarolsCircle};
int main()
{
Triangle alicesTriangle(10,10);
Rectangle bobsRectangle(10,10);
Circle carolsCircle(10);
std::map<TeamShapes, IShape*> shapeMap;
shapeMap[TeamShapes::AlicesTriangle] = &alicesTriangle;
shapeMap[TeamShapes::BobsRectangle] = &bobsRectangle;
shapeMap[TeamShapes::CarolsCircle] = &carolsCircle;
for(const auto& it : shapeMap)
{
switch (it.first)
{
case TeamShapes::AlicesTriangle:
case TeamShapes::BobsRectangle:
std::cout << static_cast<IPolygon*>(it.second)->sumOfInternalAngles() << std::endl;
std::cout << it.second->getArea() << std::endl;
break;
case TeamShapes::CarolsCircle:
std::cout << it.second->getArea() << std::endl;
break;
}
}
return 0;
}
You still have to cast your pointer, but I find it preferable to a non virtual method which throw an exception.
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...