Passing around base class pointers

c++, class-design, design-patterns, inheritance

Solution

Overload resolution in C++ happens at compile-time, not run-time. The "usual" way to solve problems like this is to use Visitor pattern.

You can reduce the amount of boilerplate copy-paste by implementing Visitor with CRTP. If you use CRTP for Base::accept, you don't need to define it any more in derived classes.

Here is a similar program to yours, but a little simpler:

#include <iostream>

class Base; class Derived;
struct Operation {
  void add(Base *b) {
    std::cout << "Base\n";
  }
  void add(Derived *b) {
    std::cout << "Derived\n";
  }
  void visit(Base *b); // need to define this after Base class

};


struct Base {
  virtual ~Base() {}
  virtual void accept(Operation &o)
  {
    o.add(this);
  }


};

void Operation::visit(Base *b) {
  b->accept(*this);
}

struct Derived : public Base {
  void accept(Operation &o)
  {
    o.add(this);
  }

};



int main() {

  Operation o;
  Base b;
  Derived d;

  Base *ptrb = &b;
  Base *ptrd = &d;
  o.add(ptrb); // These two print "Base"
  o.add(ptrd);
  o.visit(ptrb); // "Base"
  o.visit(ptrd); // "Derived"
}

Problem

Scenario: I have the following defined classes. ``` class Baseclass { }; class DerivedTypeA : public Baseclass { }; class DerivedTypeB : public Baseclass { }; // ... and so on ... class Container { list<Baseclass*> stuff; list<DerivedTypeA*> specific_stuff; // ... initializing constructors and so on ... public: void add(Baseclass * b) { stuff.add(b); } void add(DerivedTypeA * a) { stuff.add(a); specific_stuff.add(a); } }; class ContainerOperator { Container c; // ... initializing constructors and so on ... public: void operateOnStuff(Baseclass * b) { // This will always use "void add(Baseclass * b)" no matter what object b really is. c.add(b); } }; // ... containerOperator.operateOnStuff(new DerivedTypeA()); ``` So, what I want to do is to handle a certain derived class in some special way in `Container`. Problem: `void add(DerivedTypeA * a)` is never called. I'm obviously doing something wrong. What is the correct way of doing what I am trying to achieve here?

Original source