Reputation: 103
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
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
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