Home > Software engineering >  Calling overridden methods from a vector of superclass pointers
Calling overridden methods from a vector of superclass pointers

Time:04-21

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?

CodePudding user response:

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:

  1. I also declared the destructor virtual. This allows for proper destruction of an object through its base class pointer.
  2. 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.
  3. 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.

CodePudding user response:

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