Sven van den Boogaart
Sven van den Boogaart

Reputation: 12325

c++ how to call pure virtual method from multiple derived classes from one function?

Is it possible to call a pure virtual function from a loop?

Some pseudocode to explain what im trying to achive

(tried a version of the following example but got error: object of abstract class type "Base" is not allowed)

class Base{
  public:
    virtual void printMe() =0;
};

class derivedOne{
  public:
    void printMe(){std::cout << "one "<<endl;
};

class derivedTwo{
  public:
    void printMe(){std::cout << "two"<<endl;
};

class holder{
  private:
   vector<derivedOne> one;
   vector<derivedTwo> two;
   void printDerive(vector<Base> bases){
      for (Base base: bases)
      {
        base.printMe();
      }
   };
};

All derived classes implement the function printMe (because its a pure virtual function in base). Im trying to avoid writing a print loop for each class that implemented printMe from base because the functions will all do the same (loop the items in a vector and call printMe).

Upvotes: 1

Views: 232

Answers (2)

TartanLlama
TartanLlama

Reputation: 65720

You can't have a vector<Base> or have Base base in your range-based for loop, because Base is abstract and both of those require constructing a Base.

One solution would be to store std::vector<std::unique_ptr<Base>> for both one and two so that you can get dynamic dispatch:

class holder{
private:
   std::vector<std::unique_ptr<Base>> one;
   std::vector<std::unique_ptr<Base>> two;
public:
   void printDerive(const std::vector<std::unique_ptr<Base>>& bases){
      for (auto&& base: bases)
      {
        base->printMe();
      }
   };
};

Another option would be to keep your storage as-is and have a template function to print them:

class holder{
private:
   std::vector<derivedOne> one;
   std::vector<derivedTwo> two;
public:
   template <class T>
   void printDerive(const std::vector<T>& ts){
      for (auto&& t: ts)
      {
        t.printMe();
      }
   };
};

These solutions will have consequences for how you allocate the elements and use the vectors, so choose based on your other requirements.

Upvotes: 3

Smeeheey
Smeeheey

Reputation: 10336

Your problem will be creating the vector<Base>: this is not allowed, as it requires instantiation of an abstract class, Base.

You could have a vector of pointers to base, as it is only pointers (and references) that can behave polymorphically (note: your function should take the vector by const reference rather than by value):

void printDerive(const vector<std::unique_ptr<Base>>& bases){
      for (auto& base: bases)
      {
        base->printMe();
      }
};

Upvotes: 0

Related Questions