ash
ash

Reputation: 3474

base class pointer, invoke method based on derived type

I understand that the following code doesn't work -- can't convert base to foo.

Is there something I can do, or some pattern to employ which would get me close the behavior I'm trying to achieve in the code below? IOW, if I have a base class pointer to a derived type, how can I invoke a specific method that matches the derived type (not the base type)?

What patterns might I use? I looked into Curiously Recursive (or recurring) Template Pattern, however this imposed other limitations itself.

class base {};
class foo : public base {};
void method(const foo& f){}
int main(){
  base* b = new foo();
  method(*b);
}

Upvotes: 1

Views: 631

Answers (2)

Chris Drew
Chris Drew

Reputation: 15334

The easiest way is probably to just make method() a virtual member function on foo:

class base { 
 public:
  virtual void method() const = 0;
};
class foo : public base {
 public:
  void method() const override { }
};

int main(){
  foo f;
  base* b = &f;
  b->method();
}

But if for some reason that is not possible (perhaps you don't have access to method() or perhaps you want to keep the logic in method() separate from foo) you could use a simplified version of the Visitor Pattern.

The visitor pattern relies on all the classes in your hierarchy having a virtual function to dispatch based on class type.

In your case you don't need double-dispatch so you don't actually need the visitor object and can just call your method function directly from a virtual dispatch function:

class base { 
 public:
  virtual void dispatch() const = 0;
};
class foo : public base {
 public:
  void dispatch() const override;
};

void method(const foo& f){}

void foo::dispatch() const {
  method(*this);
}

int main(){
  foo f;
  base* b = &f;
  b->dispatch();
}

You have to remember that in most contexts the compiler doesn't know that your base pointer is actually of type foo.

Upvotes: 2

flogram_dev
flogram_dev

Reputation: 42858

Use virtual functions to solve these kinds of problems:

class base {
  public:
    virtual void func() const { /* A */ }
};
class foo : public base {
  public:
    void func() const override { /* B */ }
};
void method(const base& f) {
    f.func();
}
int main(){
  base* b = new foo();
  method(*b);
}

Now, depending on the actual type of f, either A or B code will be executed in method.

Upvotes: 1

Related Questions