I'd like to build a factory for my Source-Plugins like that:
class PluginFactory {
public:
PluginFactory(){};
virtual ~PluginFactory(){};
static MySource* getSourceById(int id, ParameterList& pList){
switch (id){
case 1:
return new StringSource(pList);
default:
std::cout << "Unknown PluginId!" << std::endl;
return nullptr;
}
}
};
MySource
cannot be abstract like usual in the pattern because it will later be used in a template class.
When I call a method of the returned MySource*
I get the method of the superclass MySource
instead of the overridden method of the subclass StringSource
.
Any ideas how to fix this?
EDIT:
I declared the superclass method as vritual:
MySource{
...
virtual std::streamsize read(char* s, std::streamsize n){
...
}
};
I added the override command to the subclasses' read-Method:
class StringSource: public MySource {
...
std::streamsize read(char* s, std::streamsize n) override
{
...
}
};
But it still uses the superclass method. There has to be another reason...
Btw. I put the Source-Class into a boost::iostream::filtering_istream like this:
MySource* source = PluginFactory::getSourceById(1, pluginList[0].second);
boost::iostreams::filtering_istream in;
in.push(*source);
So I don't call the read-method myself.
The problem is this:
in.push(*source);
According to the documentation, this will copy the argument. Since your base class is copyable and not abstract, you encounter the slicing problem where only the base sub-object is copied.
You should be able to fix it by passing a reference wrapper instead:
in.push(std::ref(*source));
I would suggest that you make the base class abstract (or at the very least uncopyable), to prevent the possiblity of slicing. I don't understand your reason for not making it abstract; but whatever requires it to be concrete sounds scary and error-prone.
UPDATE: Since you made it concrete just so you could pass it to this function, you should make it abstract again, and pass a reference wrapper instead.