What is the right solution to access subclass variables? - c++

How can I access sideA and height members of Triangle class, and how can I access sideA of a Square class, these are both derived from Shape class?
What is the correct way to implement that?
Shapes.h:
class Shape
{
public:
virtual double getArea() = 0;
};
class Triangle : public Shape
{
public:
double sideA = 3;
double height = 2;
double getArea() {
return 0.5 * sideA * height;
}
};
class Square : public Shape
{
public:
double sideA = 4;
double getArea() {
return sideA * sideA;
}
};
Main.cpp:
int main()
{
Shape* sh = new Triangle();
std::cout << sh->getArea() << std::endl;
std::cout << sh->??? //get the height of triangle
delete sh;
}

You are trying to access information that is not available via the interface you defined, class Shape allows only the area to be accessed.
To get also the height, the proper way is to extend the interface to provide that information as well.
class Shape
{
public:
virtual double getArea() = 0;
virtual double getHeight() = 0;
};
class Triangle : public Shape
{
public:
double sideA = 3;
double height = 2;
double getArea() {
return 0.5 * sideA * height;
}
double getHeight() {
return height;
}
};
class Square : public Shape
{
public:
double sideA = 4;
double getArea() {
return sideA * sideA;
}
double getHeight() {
return sideA;
}
};

A Shape has no height. You are using the triangle polymorphically. That means you have a Shape* and can only use the interface of Shape, no matter what is the actual type of the object. If you want a Triangle then use a Triangle not a Shape. If you still want to use a Triangle and Rectangle polymorphically, then you should put the common interface into the base class. In your case, both have a sideA, so you could do:
struct Shape {
double sideA = 3;
virtual double getArea() = 0;
virtual ~Shape(){}
};
struct Triangle : public Shape {
double height = 2;
double getArea() {
return 0.5 * sideA * height;
}
};
struct Square : public Shape {
double getArea() {
return sideA * sideA;
}
};
int main() {
Shape* sh = new Triangle();
std::cout << sh->sideA;
delete sh;
}
PS: the above wasn't the whole truth. If you have a Shape* and you know that it is a Triangle* then you could use dynamic_cast, but doings such casts are often a sign for poor design. You should strive to write classes such that you do not need a cast.

Because your base class has a virtual function1, you can use the dynamic_cast conversion to check if a pointer to it is actually a pointer to one of its derived classes. This will return nullptr if it is not of the 'tested' class, or a usable pointer to the derived class, if it is:
int main()
{
Shape* sh = new Triangle();
std::cout << sh->getArea() << std::endl;
if (dynamic_cast<Square*>(sh) != nullptr) { // Check for a valid Square pointer
Square* sq = dynamic_cast<Square*>(sh);
std::cout << sq->sideA << std::endl;
}
else if (dynamic_cast<Triangle*>(sh) != nullptr) { // Check for a valid Trianlge pointer
Triangle* tr = dynamic_cast<Triangle*>(sh);
std::cout << tr->height << std::endl;
}
else {
std::cout << "Unspecified shape type: height unknown!" << std::endl;
}
delete sh;
return 0;
1 Note that, because you have a virtual function in your Shape class, you should also give it a virtual destructor:
class Shape {
public:
virtual double getArea() = 0;
virtual ~Shape() { }
};
For further discussion on the need for a virtual destructor, see here: When to use virtual destructors?.
EDIT: In your specific case, the answer given by rustyx is really the 'correct' approach; however, it is useful to understand/appreciate the use of the dynamic_cast option, as this can be the only solution if you are deriving classes from a third-party base class, which you cannot modify, and thus cannot add the equivalent of the getHeight() function to it.

You can declare the variable a Triangle* not a Shape*, this way you'll have access to the derived class and base class methods and variables:
int main()
{
Triangle* sh = new Triangle();
Square* sh2 = new Square();
std::cout << sh->getArea() << std::endl; //3
std::cout << sh2->getArea() << std::endl; //16
std::cout << sh->sideA << std::endl; //3
std::cout << sh2->sideA << std::endl; //4
delete sh;
}
To use delete sh safely you should have a virtual destructor
class Shape
{
public:
virtual double getArea() = 0;
virtual ~Shape(){} //virtual destructor
};
Since you already have an abstract class, why not use it to access the the data in the derived classes:
Here is how I would do it:
#include <iostream>
#include <memory>
class Shape
{
private:
double sideA; //shared members can be defined in base class, assuming all
//derived classes will have sideA member
protected:
Shape(double sideA) : sideA(sideA) {}//for initialization of sideA in derived classes
public:
Shape() = default;
virtual double getArea() = 0;
double getSideA() { //shared logic
return sideA;
}
virtual ~Shape(){} //virtual destructor
};
class Triangle : public Shape
{
private:
double height = 2; //specific property
public:
Triangle() : Shape(3) {} //intialize sizeA
double getHeight(){ //specific method, must instanciate Triangle to access
//for collections it's best to use interface method like getArea()
return height;
}
double getArea() override {
return 0.5 * getSideA() * height;
}
};
class Square : public Shape
{
public:
Square() : Shape(4) {} //intialize sizeA
double getArea() override {
return getSideA() * getSideA();
}
};
int main()
{
std::unique_ptr<Shape> sh(new Triangle); //smart pointer
std::unique_ptr<Shape> sh2(new Square); //smart pointer
std::cout << sh->getArea() << std::endl; //3
std::cout << sh2->getArea() << std::endl; //16
std::cout << sh->getSideA() << std::endl; //3
std::cout << sh2->getSideA() << std::endl; //4
//delete sh; //no need, smart pointer
}
Take a look at smart pointers.

Related

Implementing interfaces in c++?

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).

Access entire base class from derived class C++

I understand that you can access members of the base class from a derived class, however, I have a function that requires a pointer to my base class as a whole. For example:
#include <iostream>
using namespace std;
function foo(Shape &s){
//does something
}
// Base class
class Shape {
public:
Shape(int w = 100, int h = 100){
width = w;
height = h;
}
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape {
public:
Rectangle(){
Shape();
}
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
foo(// Pointer Reference to Rect.Shape here);
return 0;
}
Is there any way to get a pointer to this base class from the derived class?
Here's a working version of your code. I made some changes to it and added comments to explain the changes. Your program requires polymorphism to behave as expected, otherwise you'll 'slice' your derived object and just have a Base object.
#include <iostream>
#include <string>
// Base class
// Your base should only have things that would be common to all derived classes
// Consider what the width and height of a Circle would be
//
// You may not have gotten to virtual functions and polymorphism yet. This is
// how you would set up an interface for your Derived classes. I am requiring
// any derived class to implement getArea() and identify() if it wants to be a
// 'concrete' class. Otherwise it will be abstract, which means you can't
// declare objects of that type. It is not possible to declare a Shape object
// because of the pure virtual functions
class Shape {
public:
virtual ~Shape() = default; // A virtual destructor is required
virtual double getArea() const = 0; // Pure virtual function
virtual std::string identify() const = 0;
};
// Derived class
class Rectangle : public Shape {
public:
// The base class should be initialized in the constructor's
// initialization section. What you did was declare a temporary Shape that
// went away when the function ended.
// All class data should be set in the initialization section
Rectangle(int w, int h) : Shape(), width(w), height(h) {}
double getArea() const override { return (width * height); }
std::string identify() const override { return "Rectangle"; }
private:
int width = 0;
int height = 0;
};
// A new derived class that should work (a circle **is-a** shape), but doesn't
// with your setup. Circles don't have width and height
class Circle : public Shape {
public:
Circle(int r) : Shape(), radius(r) {}
double getArea() const override { return 2 * 3.14 * radius * radius; }
std::string identify() const override { return "Circle"; }
private:
int radius = 0;
};
// Subjective, I moved the function below the class definitions and added a body
void foo(Shape &s) {
std::cout << "A " << s.identify() << " with area " << s.getArea() << ".\n";
}
int main(void) {
Rectangle rect(5, 3);
foo(rect);
Circle circ(4);
foo(circ);
return 0;
}
Output:
A Rectangle with area 15
A Circle with area 100.48
If I remove all the virtual stuff, a lot of things stop working. I now have to provide implementations for the Shape functions. That logically doesn't make much sense. And while I can pass my derived objects to foo(), they get sliced, and the filler Shape data gets printed instead.

How to copy polymorphic object

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;
}`

Correct use of polymorphism in containers?

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.

How to call different derived classes in constructors of classes derived from a different base class

In C++, I have two separate base classes, each of whose derived classes are somewhat coupled. Here's an example for the kind of thing I'd like to do:
First define a set of classes, e.g.,:
class Shape
{
public:
double area;
double diameter;
};
class Rectangle : public Shape
{
public:
double width;
double height;
};
class Circle : public Shape
{
public:
double radius;
};
The second set of classes then pertains to operations being performed on this first set of classes, something like this:
class Calculator
{
public:
static Calculator *create_calculator(shape *shape,const char *shape_type); // the factory
virtual void calculate()=0; // the actual calculation
};
class area_circles : public Calculator
{
class circles *circle;
public
area_circles(circles *circle)
{
this->circle = circle;
}
void calculate()
{
this->area = PI*pow(circle->radius,2);
}
}
class area_rectangles : public Calculator
{
class rectangles *rectangle;
public
area_rectangles(rectangles *rectangle)
{
this->rectangle = rectangle;
}
double calculate()
{
this->area = rectangle->height * rectangle->width;
}
}
Calculator *Calculator::create_calculator(shape *shape, const char *shape_type)
{
if (shape_type=="circle")
return new area_circles(shape);
if (shape_type=="rectangle")
return new area_rectangles(shape);
}
Then, the idea would be to call all this using something like:
rectangles *my_rectangle;
Calculator *area_calculator;
area_calculator = area_calculator->create_calculator(my_rectangle, "rectangle");
area_calculator->calculate();
However, this doesn't compile and I get an error (quite sensibly) pointing out how the Shape class has no member "width", and that "a value of type "shape *" cannot be assigned an entity of type "rectangles". The error's pretty clear on why this code isn't working.
Would anyone know how to get the code here to do what I'm trying to do?
From a design perspective, I recognize that part of the problem is that the derived classes end up being coupled, so maybe there is a better way to try to decouple the calculator class from the shape class. But I'd like to at least try out this approach for a while as well in my implementation, and for that I need the code to compile.
I am not entirely sure what you are trying to achieve here but I think the more usual approach to it is something like this:
class Shape
{
public:
virtual ~Shape() {}
// concrete classes must implement this function
virtual double get_area() const = 0;
};
class Circle
: public Shape
{
double diameter;
public:
Circle(double diameter): diameter(diameter) {}
virtual double get_area() const
{
return M_PI * diameter * diameter / 4;
}
};
class Rectangle
: public Shape
{
double width;
double height;
public:
Rectangle(double width, double height): width(width), height(height) {}
virtual double get_area() const
{
return width * height;
}
};
int main()
{
Circle c(2);
Rectangle r(20, 40);
// use Shape references (or pointers) to invoke polymorphic behaviour
Shape& cs = c;
Shape& rs = r;
std::cout << "Area of circle : " << cs.get_area() << '\n';
std::cout << "Area of rectangle: " << rs.get_area() << '\n';
}