I'm learning about c++ polymorphism. In the code below, a pointer called shape of the type of the base class Shape is creates and then pointed at the objects r and c.
The functions printArea(r); and printArea(c); are then called. However, at the point that these functions are called shape is pointing to the address of c. So how does it work when you call printArea(r);?
#include<iostream>
using namespace std;
class Shape {
public:
virtual float getArea() const = 0;
};
class Rectangle : public Shape {
private:
float width;
float height;
public:
Rectangle(float width, float height) : width(width), height(height) {}
float getArea() const {return width * height;}
};
class Circle : public Shape {
private:
float radius;
public:
Circle(float radius) : radius(radius) {}
float getArea() const {return 3.14159f * radius *radius;}
};
void printArea(const Shape& shape) {
std::cout << "Area: " << shape.getArea() << std::endl;
}
int main() {
Rectangle r(2,6);
Shape* shape = &r;
Circle c(6);
shape = &c;
printArea(r);
printArea(c);
printArea(*shape);
return 0;
}
I would guess your question is how, technically, is the call to getArea dispatched at run time.
The C++ standard does not prescribe this. It prescribes exactly which implementation must be executed, but not how that is accomplished.
Nearly all extant C++ implementations do that by placing a hidden pointer in each object of class with one or more virtual functions. That hidden pointer points to a table of function pointers, namely pointers to the virtual methods of the class of the object's dynamic type. This is called a vtable. And in general the call is dispatched by checking the object's vtable pointer, and retrieving the function pointer from the getArea item in the vtable, and calling that function.
There are complications for multiple inheritance, but those are just that: complications.
An alternative could be to search up the base class chain for each call.
That would be less efficient but still it's been used, at least in other languages, e.g. in original Smalltalk, and in Borlands GUI class framework for Pascal in Windows in the 1990s.
Another alternative is to place pointers to each virtual function directly in each object, essentially a vtable in each object. That approach is sometimes used in C. The main advantage is that it's conceptually simple. It also avoids one indirection. But it wastes space and doesn't generalize very well.
#include<iostream>
using namespace std;
class Shape {
public:
virtual float getArea() const = 0;
};
class Rectangle : public Shape {
private:
float width;
float height;
public:
Rectangle(float width, float height) : width(width), height(height) {}
float getArea() const {return width * height;}
};
class Circle : public Shape {
private:
float radius;
public:
Circle(float radius) : radius(radius) {}
float getArea() const {return 3.14159f * radius *radius;}
};
void printArea(const Shape& shape) {
std::cout << "Area: " << shape.getArea() << std::endl;
}
int main() {
Rectangle r(2,6);
Shape* shape = &r; // shape stores the address of object r which when further call
std::cout<< shape <<endl; //called sends its address
Circle c(6);
shape = &c; // same as r is being processed
std::cout<<shape<<endl;
printArea(r); // same thing is taking place here reference is passed and then polymorphism come
printArea(c); // into play
printArea(*shape); // as the shape was given reference of c in the end it returns its value
return 0;
}
if u still have any questions feel free to ask in comments!
Related
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.
First of all, I would like to say that I searched for similar questions, but the answers seem to focus on different things.
I started learning C++ but I have a problem understanding what exactly is considered as polymorphism. I have written two different programs.
In the first, I don't use virtual methods or pointers to objects.
In the second, I use a virtual method (area) and an array with pointers to objects.
I understand that the second program is using polymorphism (a parent class pointer is used to point to a child class object).
But since the first program produces the exact same results by overriding the function area, is it considered to be using polymorphism too?
Program 1
#include <iostream>
using namespace std;
class Polygon {
protected:
float base;
float height;
public:
Polygon(): base(0), height(0) {}
Polygon(float b, float h): base(b), height(h) {}
float area() {return -1;}
};
class Triangle:public Polygon {
public:
Triangle(): Polygon() {}
Triangle(float b, float h): Polygon(b,h) {}
float area() {return base*height/2;}
};
class Rectangle:public Polygon {
public:
Rectangle(): Polygon() {}
Rectangle(float b, float h): Polygon(b,h) {}
float area() {return base*height;}
};
int main() {
//Overriding area method without pointers
Triangle t1, t2(10,10);
Rectangle r1, r2(5,5);
cout<<t1.area()<<endl; //Output: 0
cout<<t2.area()<<endl; //Output: 50
cout<<r1.area()<<endl; //Output: 0
cout<<r2.area()<<endl; //Output: 25
cout<<t1.Polygon::area()<<endl; //Output: -1
}
Program 2
#include <iostream>
using namespace std;
class Polygon {
protected:
float base;
float height;
public:
Polygon(): base(0), height(0) {}
Polygon(float b, float h): base(b), height(h) {}
virtual float area() {return -1;} //virtual method area
};
class Triangle:public Polygon {
public:
Triangle(): Polygon() {}
Triangle(float b, float h): Polygon(b,h) {}
float area() {return base*height/2;}
};
class Rectangle:public Polygon {
public:
Rectangle(): Polygon() {}
Rectangle(float b, float h): Polygon(b,h) {}
float area() {return base*height;}
};
int main() {
//Polymorphism
Triangle t1, t2(10,10);
Rectangle r1, r2(5,5);
Polygon *ptr[]={&t1,&t2,&r1,&r2};
cout<<ptr[0]->area()<<endl; //Output: 0
cout<<ptr[1]->area()<<endl; //Output: 50
cout<<ptr[2]->area()<<endl; //Output: 0
cout<<ptr[3]->area()<<endl; //Output: 25
cout<<ptr[0]->Polygon::area()<<endl; //Output: -1
}
But since the first program produces the exact same results by overriding the function area, is it considered to be using polymorphism too?
Well, no. There's no overriding in the 1st sample, but shadowing of the base class function implementations.
That your examples produce the same results is because of the fact, that in your 1st sample
cout<<t1.area()<<endl; //Output: 0
cout<<t2.area()<<endl; //Output: 50
cout<<r1.area()<<endl; //Output: 0
cout<<r2.area()<<endl; //Output: 25
you are calling functions with concrete class instances.
Something like
Polygon *ptr[]={&t1,&t2,&r1,&r2};
cout<<ptr[0]->area()<<endl; //Output: 0
cout<<ptr[1]->area()<<endl; //Output: 50
cout<<ptr[2]->area()<<endl; //Output: 0
cout<<ptr[3]->area()<<endl; //Output: 25
would fail being used with this code.
Polymorphism means that you have some interface declared, that might be accessed through a base class reference.
In c++ you have generally the choice of
Dynamic polymorphism (i.e. abstract/virtual base classes) and resolve overridden function calls at run time
Static polymorphism (i.e. using the CRTP to resolve overridden function calls at compile time)
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';
}
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
};
class Rectangle: public Polygon {
public:
int area()
{ return width*height; }
};
int main () {
Rectangle rect;
Polygon * ppoly1 = ▭
ppoly1->set_values (4,5);
cout << rect.area() << '\n';
return 0;
}
In above example, what does ppoly1 points to and how is this pointer not able to access rectangle class's function?
WHY ppoly1->area() is an error
Thanks!
The expression ppoly1->area() is an error because ppoly1 is typed to Polygon which has no area method declared. When C++ tries to evaluate this member it essentially starts at Polygon sees no member named area and hence issues an error
It sounds like you want to give the Polygon type the notion of an area method without an implementation (forcing the derived types to provide one). If that is the case then you should declare an un-implemented virtual method in Polygon
class Polygon {
...
virtual ~Polygon() { }
virtual int area() = 0;
};
Base classes know nothing about their derived classes. When a base class is being defined there is no yet any derived class.
Variable ppoly1 is of the type Polygon *. Class Polygon has no method area so the compiler issues the error.
If you want to use a common interface for derived classes you should declare it in the base class. For example
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area() const = 0;
virtual ~Polygon(){}
};
class Rectangle: public Polygon {
public:
int area() const
{ return width*height; }
};
int main () {
Rectangle rect;
Polygon * ppoly1 = ▭
ppoly1->set_values (4,5);
cout << rect.area() << '\n';
return 0;
}
ppoly1 is a Polygon pointer. The fact that the pointer points to a Rectangle object does not enable it to call Rectangle functions; the type is still Polygon*. To enable it to call Rectangle functions you need to either make it a Rectangle pointer, or implement a virtual method in your Polygon class,
e.g.
virtual int area() const;
This means that when a Polygon object has area() called on it, it will go looking for the most derived instance of area(). On ppoly1 this will be Rectangle->area(). You can keep your Rectangle code the same as before.
Wikipedia on virtual functions: http://en.wikipedia.org/wiki/Virtual_function
I am trying to comprehend virtual functions. How so I make my put() function virtual? What changes does that necessitate in the code?
#include <iostream>
#include <string>
using namespace std;
class Circle
{
public:
Circle(double radius) {this->radius = radius; }
void put() const {cout << "Radius = " << radius;}
private:
double radius;
};
class ColoredCircle: public Circle
{
public:
ColoredCircle(double radius, string color);
void put() const;
private:
string color;
};
ColoredCircle::ColoredCircle(double radius, string color)
: Circle(radius), color(color) {}
void ColoredCircle::put() const
{
Circle::put();
cout << " Color = " << color;
}
int main()
{
ColoredCircle redCircle(100., "red");
Circle* circle1 = &redCircle;
circle1->put();
cout << endl;
Circle circle(50.);
Circle* circle2 = &circle;
circle2->put();
cout << endl;
std::cin.get();
return 0;
}
You just have to write the virtual keyword in front of the function in the base class :
class Circle
{
public:
Circle(double radius) {this->radius = radius; }
virtual void put() const {cout << "Radius = " << radius;}
// ^^^^^^^
private:
double radius;
};
But you should understand the case where the virtual functions are used. What is the performances cost, why it is useful, etc ...
A little piece of answer : A virtual method is a special of method whose the behavior can be overriden within an inheriting class with amethod of the same signature.
About the performance cost : There is definitely measurable overhead when calling a virtual function - the call must use the vtable to resolve the address of the function for that type of object. The extra instructions are the least of your worries. Not only do vtables prevent many potential compiler optimizations, they can also thrash your I-Cache.
Of course whether these penalties are significant or not depends on your application, how often those code paths are executed, and your inheritance patterns.
I would suggest you to read some articles about virtual functions, here is a non exhaustive list :
http://www.cplusplus.com/doc/tutorial/polymorphism/
http://en.wikipedia.org/wiki/Virtual_function
http://www.learncpp.com/cpp-tutorial/122-virtual-functions/
What is the performance cost of having a virtual method in a C++ class?