So I'm new to learning about virtual functions, and I'm following online tutorials and I can't seem to find an answer to my question. I want to ask why using virtual functions below by setting base class objects to point to derived class objects, is preferable to just using the derived class objects themselves to access the functions?
It seems that I get the same output either way, and it seems creating base class objects and virtual functions are extra steps. I saw a similar example to this on an online tutorial which claimed virtual functions made coding easier but I don't quite see the benefit in this example?
I read online that:
The main advantage of virtual functions are that they directly support object oriented programming. When you declare a function as virtual you're saying that exactly what code is executed depends on the type of the object you call it against.
But it seems this is already the case using derived objects, and that creating base class objects is unnecessary? I'm sure that I'm missing something obvious so I would really appreciate any help. I showed an example code I wrote below which is similar to what I've seen when detailing virtual functions:
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
//base class
class Shape {
public:
virtual void draw()=0; //pure virtual function
};
//derived classes
class Square : public Shape {
public:
void draw() {
cout << "Draw square" << endl;
}
};
class Circle : public Shape {
public:
void draw() {
cout << "Draw circle " << endl;
}
};
//////////////////////////////////////////////////////
int main()
{
Square so; //create derived class objects
Circle co;
Shape* shape1 = &so; //setting base class objects as pointers to derived objects
Shape* shape2 = &co;
shape1->draw(); //using base class objects to access derived class
shape2->draw();
so.draw(); //using derived class objects
co.draw();
}
The huge benefit that you get for using the base class pointer type and virtual functions is that you can have one single list that contains several different types of Shape and you can process them all in a single function where they will all have different behaviors due to their derived types.
As an example, I modified your code by adding the function DrawAllShapes that takes in a vector<Shapes*>&. (Be careful of using raw pointers. You really should use vector<std::unique_ptr<Shape>>&here or something like that.
You have incredible flexibility with this pattern that lets you call the same function on a collection of base class pointer objects but results in different behavior for every object in the collection depending on its derived type.
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
//base class
class Shape {
public:
virtual void draw() = 0; //pure virtual function
};
//derived classes
class Square : public Shape {
public:
void draw() {
cout << "Draw square" << endl;
}
};
class Circle : public Shape {
public:
void draw() {
cout << "Draw circle " << endl;
}
};
void DrawAllShapes(std::vector<Shape*>& shapes) {
for (int i = 0; i < shapes.size(); ++i) {
shapes[i]->draw();
}
}
//////////////////////////////////////////////////////
int main()
{
std::vector<Shape*> shapeVec{ new Square, new Circle, new Square, new Square, new Circle };
DrawAllShapes(shapeVec);
system("pause");
}
Also, imagine if you were using a prebuilt graphical library that already had a Shape class and several shapes defined. What if you wanted to add your own new type of Shape and have it work perfectly with all of the library's functions? All you would have to do is create your own derived class and implement all of the necessary virtual functions exposed by the library's Shape class and then you've literally extended the library beyond its original capabilities.
In an arbitrary physics engine for a game, there exists a "Shape" superclass and its derived subclasses such as "AABB" or "Triangle". Collision detection methods between each pair is unique, for example the AABB-Sphere test will obviously be different from the Triangle-AABB test. If I have two collections of shapes as such and I wish to check some collisions between them:
// somewhere in the program
Shape* shape_a;
Shape* shape_b;
....
if (shape_a->intersects(shape_b)) {
// do something
}
How can specific collision checks (e.g. AABB-ABBB, or AABB-Sphere) be performed? For example, if shape_a points to a derived Triangle object, and shape_b performs to a derived AABB object, how can the intersects function correctly compare a Triangle and AABB object? My current implementation is as follows but it does not compile as an include loop is created (likely due to bad OOP practice).
Shape.h
#include "AABB.h"
#include "triangle.h"
class Shape {
public:
virtual bool intersects(Shape* shape) = 0;
virtual bool intersects(AABB aabb) = 0;
virtual bool intersects(Triangle tri) = 0;
}
AABB.h
#include "shape.h"
class AABB : public Shape {
// overriden functions
bool intersects(Shape* shape);
bool intersects(AABB aabb); // aabb-aabb
bool intersects(Triangle tri); // aabb-tri
}
triangle.h
#include "shape.h"
class Triangle : public Shape {
// overriden functions
bool intersects(Shape* shape);
bool intersects(AABB aabb); // tri-aabb
bool intersects(Triangle tri); // tri-tri
}
The implementation for an intersects(Shape* shape) function looks like:
// in AABB.cpp
bool intersects(Shape* shape) {
return shape.intersects(*this); // where *this is an AABB object
}
And of course, I want to avoid code duplication: the tri-aabb test is the same as the aabb-tri test. Perhaps I am writing code that is fundamentally flawed and is bad OOP practice. In any case, I'd appreciate any help with this problem!
To avoid the include loop you can just forward-declare the AABB and Triangle classes in shape.h:
class AABB;
class Triangle;
To avoid duplicating code based on parameter order you can have a separate function with a canonical order for each overloading pair, and call it with the different orders from the member functions:
bool intersects( AABB *, Triangle * );
AABB::intersects( Triangle *t ) { return intersects( this, t ); }
Triangle::intersects( AABB *b ) { return intersects( b, this ); }
I'm new in C++ and I have maybe easy for you question.
class circle {
protected:
int r;
public:
circle(int re) { r=re; }
double surface() {
return 3.14*r*r;
}
};
class sphere : public circle {
public:
sphere(int r) : circle(r) {}
double surface(){
return 4*3.14*r*r;
}
};
And now, my problem is how I can do something like that: create a sphere object and using it to get surface not of a sphere but of a circle. Can I use somehow the same methods names in two classes, when one is inherited by the second one?
You can have access to the base class' surface method by appending circle:: before its name :
sphere sph(1);
double s = sph.circle::surface();
Your design is initially wrong. Public inheritance in C++ means that the child is-a specific kind of the parent. A sphere is not a circle!
Besides, if you do want to get the surface area of the sphere, you should make your surface function virtual:
class Circle {
public:
virtual double surface();
};
That way, when you override it in Sphere, the Sphere version will be called.
I'm not sure if I phrased my question as well as I liked to but I'll give an example to clear things up.
Here is the code:
class Shape;
class Circle;
class Triangle;
class Shape
{
Shape(void);
~Shape(void);
virtual void DrawShape(void) = 0;
}
class Circle : public Shape
{
/* .... constructor/destructor defined normally .... */
bool TestIntersection(Triangle* _triangle);
bool TestIntersection(Circle* _circle);
void DrawShape(void);
}
/* main.cpp */
...
Shape* shape;
Shape* circle = new Circle;
if(a == 0)
{
shape = new Circle;
}
else
{
shape = new Triangle;
}
circle->TestIntersection(shape);
I get the error that there is no acceptable conversion from Shape* to Circle* or Triangle*.
Why is this happening? Or do I need a way to determine which derived class has been set to the abstract class pointer?
What you need basically is this:
Visitor pattern
I noticed that you have not derived your supposedly derived classes from Shape. Fix that also. That is, Triangle and Circle should be derived from Shape. After that, read about Visitor pattern, its various implementations and usage. That will help you in solving your problem.
This is happening because you have actually not derived from the Shape.
class Circle: public Shape {
...
};
Your Circle class doesn't seem to inherit from Shape:
Try this:
class Circle : Shape
{
}
In a C++ physics simulation, I have a class called Circle, and Square. These are Shapes, and have a method called push(), which applies force to it. There is then a special case of Circle, call it SpecialCircle, in which push() should exhibit slightly different properties. But in fact, there is also SpecialSquare() which should exhibit the same force properties. So I'd like to have an abstract base class called Shape which takes care of Circles and Squares, but then I'd also like an abstract base class called Special, which applies special properties to force().
What's the best way to design this class structure?
So far, I've got:
class Shape {
virtual void push();
};
class Circle : public Shape {};
class Square : public Shape {};
class Special {
virtual void push();
};
class SpecialCircle : public Circle, Special {};
class SpecialSquare : public Square, Special {};
Of course, the above won't compile, since Special::push() and Shape::push() conflict. I get "error: request for member ‘push’ is ambiguous", as expected.
How can I re-organize my class structure so that Circle and Square can share certain properties with each other, but SpecialCircle and SpecialSquare can still inherit from Shape, and also inherit modified functionality from Special?
Thanks.
ps., is this the diamond inheritance problem?
Another solution (it may or may not fit your needs, it depends on the details of your implementation):
Have the class Behavior, and let NormalBehavior and SpecialBehavior inherit from it.
Have the class Shape, and let Square and Circle inherit from it. Let Shape be an aggregate type, with a Behavior member (i.e. you pass a Behavior object to the various Shape constructors). In other words, let a Shape have a Behavior.
Delegate the actual differences in the behavior of shapes to methods of the Behavior hierarchy.
Conversely, you can:
Have the class PhysicalObject, and let NormalObject and SpecialObject inherit from it;
Have the class Shape, and let Square and Circle inherit from it;
Let a PhysicalObject have a Shape.
Prefer aggregation over inheritance. This is an application of the Bridge pattern. The advantage of this strategy with respect to having Square, SpecialSquare, Circle, and SpecialCircle, is that tomorrow you'll have to add Rectangle, Hexagon and so on, and for each shape you add you'll have to implement two classes (duplicated code is evil); this is, in my opinion, the real issue that Bridge addresses.
It's said that every problem in software can be solved by adding an additional layer of indirection.
Herb Sutter has an excellent article on how to solve your problem: Multiple Inheritance - Part III
In short, you use intermediate classes to 'rename' the virtual functions. As Herb says:
Renaming Virtual Functions
If the two inherited functions had different signatures, there would be no problem: We would just override them independently as usual. The trick, then, is to somehow change the signature of at least one of the two inherited functions.
The way to change a base class function's signature is to create an intermediate class which derives from the base class, declares a new virtual function, and overrides the inherited version to call the new function
Here's a long example using your classes:
class Shape {
public:
virtual void push() = 0;
};
class Circle : public Shape
{
public:
void push() {
printf( "Circle::push()\n");
}
};
class Square : public Shape
{
public:
void push() {
printf( "Square::push()\n");
}
};
class Special {
public:
virtual void push() = 0;
};
class Circle2: public Circle
{
public:
virtual void pushCircle() = 0;
void push() {
pushCircle();
}
};
class Square2: public Square
{
public:
virtual void pushSquare() = 0;
void push() {
pushSquare();
}
};
class Special2 : public Special
{
public:
virtual void pushSpecial() = 0;
void push() {
pushSpecial();
}
};
class SpecialCircle : public Circle2, public Special2
{
public:
void pushSpecial() {
printf( "SpecialCircle::pushSpecial()\n");
}
void pushCircle() {
printf( "SpecialCircle::pushCircle()\n");
}
};
class SpecialSquare : public Square2, public Special2
{
public:
void pushSpecial() {
printf( "SpecialSquare::pushSpecial()\n");
}
void pushSquare() {
printf( "SpecialSquare::pushSquare()\n");
}
};
int main( int argc, char* argv[])
{
SpecialCircle sc;
SpecialSquare ss;
// sc.push(); // can't be called - ambiguous
// ss.push();
sc.pushCircle();
ss.pushSquare();
Circle* pCircle = ≻
pCircle->push();
Square* pSquare = &ss;
pSquare->push();
Special* pSpecial = ≻
pSpecial->push();
pSpecial = &ss;
pSpecial->push();
return 0;
}
Rather than thinking of code reuse through inheritance, the use of mixins will give you the code reuse you want without the problems of multiple inheritance.
If you are unfamiliar with the technique, do a search on SO or Google. Make sure you search for both "mixin" and "Curiously Recurring Template Pattern". There are heaps of great articles around to get you started.
When you have to inherit from multiple interfaces with the same method the compiler can't tell which one are you trying to call, you can fix this by overriding such method and call the one you want.
class SpecialCircle : public Circle, Special {
public:
virtual void push() { Special::push(); }
};
class SpecialSquare : public Square, Special {
public:
virtual void push() { Special::push(); }
};
But in this case I think the correct OO approach is to factor out the push behavior in its own class, like Federico Ramponi have suggested.
Have a SpecialShape from Shape and SpecialCircle and SpecialSquare from SpecialShape.
Well, if the special and normal circles can be both applied forces to, and the special circle has another method that applies special forces, why not have two interfaces and two methods?
struct Applicable {
virtual ~Applicable() { }
// if it applies force, better be explicit with naming it.
virtual void applyForce() = 0;
};
struct SpecialApplicable {
virtual ~SpecialApplicable() { }
virtual void applySpecialForce() = 0;
};
struct Shape {
virtual ~Shape() { }
Size getSize();
Point getPosition();
// ...
};
struct Circle : Shape, Applicable {
virtual void applyForce() { /* ... */ }
}
struct SpecialCircle : Circle, SpecialApplicable {
virtual void applySpecialForce() { /* .... */ }
};
If it doesn't make sense if there is both a special and a normal apply method (which the name of the class - SpecialCircle - suggests), then why not do even this:
struct Circle : Shape, Applicable {
virtual void applyForce() { /* ... */ }
}
struct SpecialCircle : Circle {
// applies force, but specially
virtual void applyForce() { /* .... */ }
};
You can also put the applyForce into the Shape class. It also depends on the environment in which those classes are used. What, in any case, you really should avoid is having the same method in two base classes that appear in two difference base-lattices. Because that inevitable will lead to such ambiguity problems. The diamond inheritance is when you use virtual inheritance. I believe there are other good answers on stackoverflow explaining that. It isn't applicable for your problem, because the ambiguity arises because the method appears in two base class sub-objects of different types. (It only solves such cases where the base classes have the same type. In those cases, it will merge the base classes and there will only be one base class sub-object contained - inherited by virtual inheritance)