I am currently writing a small game in OpenGL using C++. Coming from a non-C++ background, I have a simple question about overriding methods and how to call them using a pointer of a superclass type.
This is the case: I have a class Polygon containing the method void draw(). This class has two children called Rectangle and Circle, which both override the drawing method, as I am using different OpenGL calls depending on the type of polygon being drawn.
Now consider this: I wish to store all polygons (including both rectangles and circles) in an std::vector<Polygon*>. This is perfectly fine. However, iterating through the vector and calling draw automatically resorts to the superclass' version of the method.
How can I make a vector of type superclass-pointer, store pointers to subclass objects in it, and call overridden functions depending on the actual type of the object being used?
You are describing polymorphism (or a lack thereof in your current implementation).
To make your draw function polymorphic, you must declare it virtual. See below for an example:
class Polygon {
public:
virtual ~Polygon() {}
virtual void draw() = 0;
};
class Rectangle : public Polygon
{
public:
void draw() override { std::cout << "Rectangle::draw()\n"; }
};
class Circle : public Polygon
{
public:
void draw() override { std::cout << "Circle::draw()\n"; }
};
Note three extra things in the above:
I also declared the destructor virtual. This allows for proper destruction of an object through its base class pointer.
I declared the base draw method as pure-virtual (the = 0 part). This means the Polygon class is abstract and cannot itself be instantiated. You may not want that, but to me it seems there's no use for a draw method on a base class anyway. Define one if you want. Up to you.
The override specifier is optional, but recommended (language feature introduced by C++11). It instructs the compiler that you're intentionally overriding a virtual method, and so if no such method exists to be overridden then it will generate a compiler error.
You need to define the function as virtual in the base class and the override it in the subclasses. For example
#include <vector>
#include <iostream>
struct A{
virtual void p(){std::cout<<"A ";}
A(){}
virtual ~A() {};
};
struct B: public A{
void p()override{std::cout<<"B ";}
B(): A(){}
};
struct C: public A{
void p()override{std::cout<<"C ";}
C() : A(){}
};
int main()
{
A* a=new A();
B* b=new B();
C* c=new C();
std::vector<A*> v={a,b,c};
for(auto i : v)
i->p();
std::cout<<"\n";
delete a;
delete b;
delete c;
return 0;
}
prints "A B C".
Related
I am sorry but I have to ask a stupid question.
I understand the benefit of implementing an abstract class as such. If I have virtual function with a basic implementation that is always called in cases when the derived classes don't have a specific implementation there is definitely a benefit, e.g.
virtual void ImplementedVirtFunc() {//do something basic}
What I don't quite get is what is the benefit of implementing a purely virtual function such as
virtual void VirtFunc() = 0;
In this case my derived classes need to implement the specialisized function anyhow if they need it. But I could straight forwardly just implement it there and omit the virtual void VirtFunc() = 0 line in my abstract class.
So is there a specific benefit for implementing virtual void VirtFunc() = 0 that I don't see?
Please forgive me this stupid question. I started to learn C++ this January and I am still have a long way to go to understand all the subtleties...
But I could straight forwardly just implement it there and omit the virtual void VirtFunc() = 0 line in my abstract class.
Sure, you could. But you wouldn't be able to call that method from your base class, since your base class doesn't know anything about its existence at all.
Consider the following example. Every Shape definitely has an area, even though not known for a general shape. And every subclass of Shape inherits the Print() method.
class Shape {
// ...
public:
virtual int Area() = 0; // there is no formula for the area of a "general" shape, but it definitely has one ...
virtual void Print() {
std::cout << "Area: " << Area() << std::endl;
}
}
class Circle : public Shape {
// ...
public:
virtual int Area() {
// calculate and return circle area
}
}
class Square : public Shape {
// ...
public:
virtual int Area() {
// calculate and return square area
}
}
virtual void f(); // virtual member function
virtual void g() = 0; // pure abstract member function
A class with at least one pure virtual member function is an abstract class, and cannot be constructed itself, which is often desired (only non-abstract, "concrete" if you will, derive classes should be able to be constructed);
struct Abstract {
virtual void g() = 0;
};
struct NonAbstract {
virtual void f() {}
};
int main() {
NonAbstract na{}; // OK
Abstract a{}; // Error: cannot declare variable 'a'
// to be of abstract type 'Abstract'
}
Abstract classes are typically used polymorphically, to allow dynamic dispatch to derived object methods:
struct Derived : public Abstract {
void g() override {} // #1
}
void h(Abstract const& obj) {
obj.g(); // dynamic dispatch
}
int main() {
Derived d{};
h(d); // Will result in invoke #1
}
There are two reasons.
One is to force the derived concrete class to implement your virtual function.
The second is to make your class an abstract class, which cannot be instantiated by itself.
I have this:
class Base {
public:
Base() {};
virtual ~Base() = default;
virtual void Draw() = 0;
};
class Derived_1 {
public:
Derived_1() {};
void Draw() { std::cout << "Draw()" << std::endl; };
};
class Derived_2 : public Base, public Derived_1 {
public:
Derived_2() {};
~Derived_2() {};
//void Draw() { Derived_1::Draw(); }; <<<<<===--- This works well
};
class Derived_3 : public Derived_2 {
public:
Derived_3() {};
~Derived_3() {};
};
int main()
{
Base* d = new Derived_3();
d->Draw();
return 0;
}
I got an error like "pure virtual function "Base::Draw" has no overrider". I think the problem is Derived_2 has two Draw() functions, one of which is virtual. However, I don't know how to fix this without adding wrapper function Draw() in Derived_2 class. Is it possible?
When you give your Derived_2 class multiple inheritance (i.e., it derives from both Base and Derived_1) you are saying that it inherits the member functions from both base classes.
In this case, that will mean that it has two (different) Draw members with the same signatures. Thus, the pure virtual Draw function derived from Base will not be overriden by that derived from Derived_1.
In fact, if you use Derived_3* d = new Derived_3(); in place of your first line of main(), as suggested, you will still get the "cannot instatiate abstract class" error, plus another one along the lines of "amibuguous access of Draw()".
Your commented-out line, void Draw() { Derived_1::Draw(); }; in the Derived_2 class does two things: (1) It resolves the ambiguity in any later call to Draw() from a Derived_2 class; and (2) it provides a viable override of the pure-virtual Draw function of the Base class.
The two Draw functions are distinct, despite the similarities in name and signature. They could just as well have two different names. Base and Derived_1 are unrelated, so Derived_1's Draw cannot override Base's.
If Base::Draw was not pure virtual, the call to d->Draw() in main would be ambiguous, because the compiler would not know which draw to call.
The solution is what you have commented out: provide a Draw in Derived_2 that will call the one in Derived_1. (Not relevant here, but in the alternative where Base::Draw is not pure virtual, Derived_2::Draw might need to call the Draw function in both base classes.)
I think your problem is that you defined d as class “Base”, instead of class “Derived_3”, so even though you used the derived_3 constructor the compiler is looking for a definition of draw under “Base.”
you have 2 functions with the same name and arguments, that is never good. try either changing the name of one of the Draw() functions or, if you really want the same name, making Derived_1 inherit from Base
I am trying to add a number of subclassed elements into a vector, iterate through them calling a overridden method and want it to call the overridden method where possible. However I have found that it appears to only be calling the superclass method.
I learnt Java and am unsure why it is doing this in C++. I have tried rewriting the code using a vector of pointers of the superclass and casting the pointer of the subclass to the superclass. Accessing this through pointers then works.
Ideally I dont want to have to put a list of pointers into the vector since then I have to manually delete each one (I believe?) to stop memory leaks since I will be creating the objects with new so they persist past the method call to add them into the vector.
Is there a better way to do this or am I stuck to using pointers and calling delete on the created objects when the parent class is unneeded? Preferably the vector would be a list of class X rather than a list of pointers of class X
My structure is:
class a { vector vec of class X,
method to create and add an instance of X into vector vec,
method to create and add an instance of Y into vector vec }
class X { talk() }
class Y : public X { talk() }
Code to demonstrate what I ideally want to do, but showing its broken by only calling the superclass method:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
class A {
public:
virtual void talk() { printf("A\n"); }
};
class B: public A {
public:
void talk() { printf("B\n"); }
};
int main(void) {
std::vector<A> vec;
std::vector<A*> vec2;
A a;
B b;
a.talk();
b.talk();
vec.push_back(a);
vec.push_back(b);
vec2.push_back(&a);
vec2.push_back(&b);
for(int i = 0; i < vec.size(); i++) {
vec[i].talk();
vec2[i]->talk(); //bad but short for example
}
}
To get the polymorphic behaviour you want you need to add the virtual specifier to the functions in the base class that you want to override in derived classes.
class A {
public:
virtual void talk() { printf("A\n"); }
};
You should also make a habit of adding the override specifier on overridden functions in derived classes so that the compiler can help you with these kind of issues.
class B: public A {
public:
virtual void talk() override { printf("B\n"); }
// ^ Compiler will report an error if base class' function
// is not virtual.
};
Also you can not assign a derived object to an instance of a base class, or slicing will occur.
std::vector<A> vec;
/* ... */
B b;
/* ... */
vec.push_back(b); // Slicing. Information only in B is lost.
Live example using virtual specifier
Live example without virtual specifier
You should declare the methods as virtual in order to be able to override them in a subclass. Also it's good practice to make the destructor virtual.
class A {
public:
virtual void talk() { printf("A\n"); }
virtual ~A(){}
};
class B: public A {
public:
// using virtual is not really necessary here, but it's good for clarity.
virtual void talk() { printf("B\n"); }
};
The method should be virtual.
In java methods are virtual by default.
class A {
public:
virtual void talk() { printf("A\n"); }
};
class B: public A {
public:
virtual void talk() override { printf("B\n"); } //override key word is in C++ 0x and above
};
I think what you are missing is the virtual keyword in your method declaration. If you want to get to a subclass method when invoking methods in a parent class, the methods have to be declared virtual.
If you don't use a pointer you will get 'object slicing' when you copy the object into the vector. This reduces the object to the base type declared in the vector template argument. So there is no subclass, so no subclass method to call, even if the method is virtual.
I'm slightly confused about runtime polymorphism. Correct me if I am wrong, but to my knowledge, runtime polymorphism means that function definitions will get resolved at runtime.
Take this example:
class a
{
a();
~a();
void baseclass();
}
class b: class a
{
b();
~b();
void derivedclass1();
}
class c: class a
{
c();
~c();
void derivedclass2();
}
Calling methodology:
b derived1;
a *baseptr = &derived1; //here base pointer knows that i'm pointing to derived class b.
baseptr->derivedclass1();
In the above calling methodology, the base class knows that it's pointing to derived class b.
So where does the ambiguity exist?
In what cases will the function definitions get resolved at runtime?
This code, at run time, calls the correct version of f() depending on the type of object (A or B) that was actually created - no "ambiguity". The type cannot be known at compile-time, because it is selected randomly at run-time.
struct A {
virtual ~A() {}
virtual void f() {}
};
struct B : public A {
virtual void f() {}
};
int main() {
A * a = 0;
if ( rand() % 2 ) {
a = new A;
}
else {
a = new B;
}
a->f(); // calls correct f()
delete a;
}
There is no ambiguity exists in the example provided.
If the base class has the same function name as the derived class, and if you call in the way you specified, it will call the base class's function instead of the derived class one.
In such cases, you can use the virtual keyword, to ensure that the function gets called from the object that it is currently being pointed. It is resolved during the run time.
Here you can find more explanation..
Turn this
void baseclass();
to
virtual void baseclass();
Override this in your Derived classes b and c. Then
b *derived1 = new derived1 ();
a *baseptr = derived1; //base pointer pointing to derived class b.
baseptr->baseclass();
will invoke derived1 definition, expressing run time polymorphism. And do remember about making your destructor virtual in Base. Some basic reading material for polymorphism
Runtime means that exact method will be known only at run time. Consider this example:
class BaseClass
{
public:
virtual void method() {...};
};
class DerivedClassA : public BaseClass
{
virtual void method() {...};
};
class DerivedClassB : public BaseClass
{
virtual void method() {...};
};
void func(BaseClass* a)
{
a->method();
}
When you implement your ::func() you don't know exactly type of instance pointed by BaseClass* a. It might be DerivedClassA or DerivedClassB instance etc.
You should realize, that runtime polymorphism requires special support from language (and maybe some overhead for calling "virtual" functions). In C++ you "request" for dynamic polymorphism by declaring methods of base class "virtual" and using public inheritance.
You need to have some useful business method declared in the base and in each derived class. Then you have code such as
a->someMethod();
Now the a pointer might point to an instance of any of the derived classes, and so the type of what a is pointing to must determine which someMethod() is called.
Lets have an experiment
#include <iostream>
using namespace std;
class aBaseClass
{
public:
void testFunction(){cout<<"hello base";}///Not declared as virtual!!!!
};
class aDerivedClass:public aBaseClass
{
public:
void testFunction(){cout<<"hello derived one";}
};
class anotherDerivedClass:public aDerivedClass
{
public:
void testFunction(){cout<<"hello derived two";}
};
int main()
{
aBaseClass *aBaseClassPointer;
aBaseClassPointer=new aDerivedClass;
aBaseClassPointer->testFunction();
}
The above code does not support run time polymorphism. Lets run and analyze it.
The output is
hello base
Just change the line void testFunction(){cout<<"hello base";} to virtual void testFunction(){cout<<"hello base";} in aBaseClass. Run and analyze it. We see that runtime polymorphism is achieved. The calling of appropriate function is determined at run time.
Again change the line aBaseClassPointer=new aDerivedClass to aBaseClassPointer=new anotherDerivedClass in main function and see the output. Thus the appropriate function calling is determined at run time (when the program is running).
I would like to do this:
class Derived;
class Base {
virtual Derived f() = 0;
};
class Derived : public Base {
};
Of course this doesn't work since I can't return an incomplete type. But neither can I define Derived before base, since I can't inherit from an incomplete type either. I figure that I could use templates as a workaround (using Derived as a template argument to Base), but it seems a really ugly way of doing things. Might there be another way?
Elaboration: I'm writing a raytracer, and each Shape class has a function which returns its bounding box. However, I've made the BBox a subclass of Shape, so I can visualize it. Is this bad design?
There's nothing wrong with the code in your question. This
class Derived;
class Base {
virtual Derived f() = 0;
};
class Derived : public Base {
virtual Derived f() {return Derived();}
};
should compile just fine. However, callers of 'Base::f()' will need to have seen the definition of 'Derived`.
You could use a pointer (or a reference):
class Derived;
class Base {
virtual Derived *f() = 0;
};
class Derived : public Base {
};
But this is code smell to me. Why should anybody inheriting from this class need to know about another derived class? In fact, why should the base class be concerned with it's derivee's?
For your situation, you'll need to notice things that mgiht be a signal for bad design. Although it makes sense that your bounding box would derive from Shape, keep in mind, since Shape has a function that returns a bounding box, a bounding box will have a function that returns itself.
I'm not sure the best solution, but you could make BBox a separate class altogether, and perhaps give it a function akin to: Shape *as_shape(void) const, which would construct a class Box : public Shape with the same dimensions as the bounding box.
I still feel there is a better way, but I'm out of time for now, I'm sure someone else will think of a better solution.
Your notion about templates wasn't necessarily a bad one. What you describe is called the Curiously Recurring Template Pattern.
An example:
#include <iostream>
template <typename T>
struct Base
{
virtual T* foo() = 0;
};
struct Derived : Base<Derived>
{
virtual Derived* foo() { return this; }
};
Why not just do:
class Base {
virtual Base *f() = 0;
};
I'd go with returning a pointer to a Base, so that Base doesn't need to know about Derived or anything else that comes along later:
class Base {
virtual Base *f() = 0;
};
class Derived : public Base {
virtual Base *f();
};
Base *Derived::f() {
Derived *r = new Derived;
return r;
}
As others have pointed out, the code sample you have can be made to work, but that you probably mean to return a pointer to the base class from f().
In your elaboration, you mention that the bounding box is a subclass of shape, but there is a problem:
class Shape{
virtual Shape* getBoundingBox() = 0;
};
class Square: public Shape{
virtual Shape* getBoundingBox();
};
class BBox: public Shape{
virtual Shape* getBoundingBox(); // Whoops! What will BBox return?
};
Lets move some of the responsibilities around:
class Shape{
virtual void draw() = 0; // You can draw any shape
};
class BBox: public Shape{
virtual void draw(); // This is how a bounding box is drawn
};
class BoundedShape: public Shape{
virtual BBox* getBoundingBox() = 0; // Most shapes have a bounding box
};
class Square: public BoundedShape{
virtual void draw();
virtual BBox* getBoundingBox(); // This is how Square makes its bounding box
};
Your application will now probably need to hold collections of BoundedShape* and occasionally ask one for its BBox*.