Jase Uknow
Jase Uknow

Reputation: 103

C++: How to obtain different behaviour for methods of abstract-derived classes from the derived classes of another abstract class?

I have two abstract classes, fooBase and barBase. They both have two (or more) concrete child classes (foo1, foo2 and bar1,bar2). I want a method of each of the child classes of barBase to call a method corresponding to one of the concrete classes in fooBase. For example,

class fooBase{
    virtual int method()=0;
};

class foo1 : public fooBase {
    public :
    foo1(){}
    int method(){return 1;}
};

class foo2 : public fooBase {
    public :
    foo2(){}
    int method(){return 2;}
};

class barBase {
    virtual int drilldown(fooBase &)=0;
};

class bar1 : public barBase {
    public :
    bar1(){}
    int drilldown(foo1 & f){return f.method();}
};

class bar2 : public barBase {
    public :
    bar2(){}
    int drilldown(foo2 & f){return f.method();}
};

and then in main() do:

    foo1 f1;
    foo2 f2;
    bar1 b1;
    bar2 b2;

But I get the error: Variable type 'b1' is an abstract class (likewise for b2). I know that this is happening because the method drilldown in barBase is defined with a parameter that is a reference to the fooBase abstract class but bar1 and bar2 are trying to drill down into the concrete child classes so compiler doesn't recognise that the method for drilldown(fooBase &) is defined in the child classes. How can I fix this so that I get the behaviour that I want? What is the right design pattern for this situation?


I ended up using the solution by Joachim Pileborg (see below). I also had to change any functions with arguments barBase &, to template functions i.e.,

 template<class T>
 int fn(barBase<T> & b, T & f){
    return b.drilldown(f);
 }


int main(int argc, const char * argv[]) 
{
    foo1 f1;
    foo2 f2;
    bar1 b1;
    bar2 b2;
    std::cout<<b1.drilldown(f1);
    fn(b1,f1);
return 0;
}

Upvotes: 0

Views: 111

Answers (2)

quamrana
quamrana

Reputation: 39404

It seems that you only need:

class barBase {
    int drilldown(fooBase &f){ return f.method(); }
};

and your supposed function:

int f(barBase & b, fooBase & f){return b.drilldown(f);}

will work just fine.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409432

You can define barBase as a template, like

template<typename T>
struct barBase {
    virtual int drilldown(T &)=0;
};

class bar1 : public barBase<foo1> {
    public :
    bar1(){}
    int drilldown(foo1 & f){return f.method();}
};

class bar2 : public barBase<foo2> {
    public :
    bar2(){}
    int drilldown(foo2 & f){return f.method();}
};

Of course it has the drawback that you can't use pointers or references to barBase to refer to either of its child classes.

Upvotes: 0

Related Questions