Edit: My question might just be asking how to downcast a unique_ptr<base>
to unique_ptr<derived>
(which is already answered), but I am not 100% sure what I am asking
I have an Abstract Base Class Base
class Base{
public:
Base();
struct pStruct{};
virtual pStruct pFunc(std::vector<double> data) = 0;
protected:
CustomType dataValue;
};
and two derived classes Derived1
and Derived2
that implement Base
class Derived1 : public Base {
public:
struct pStructD1 : Base::pStruct {
CustomType data1;
std::vector<double> data2;
};
Derived1(uint32_t foo1, std::vector<double> foo2, ...);
virtual pStruct pFunc(std::vector<double> data) override;
private:
uint32_t bar1{0};
};
class Derived2 : public Base {
public:
struct pStructD2 : Base::pStruct {
int32_t data3;
std::vector<double> data4;
double data5
};
Derived2(std::vector<double> foo1, std::vector<double> foo2, ...);
virtual pStruct pFunc(std::vector<double> data) override;
private:
std::vector<double> bar2;
};
When calling class method pFunc(std::vector<double> data)
, each derived class will return different types, and amounts of values. I tried making this work with a covariant return type, so Derived1::predict(data).key1
might be a matrix, and .key2
might be something else, and so on. Derived2::predict(data).key1
might be the only key, and it could be a boolean. Each derived class defines their own ::predict()
return fields, because they vary significantly.
The issue is, I construct these derived classes with a factory, that reads some of the input (construction is via ifstream), and figures out what derived class it should be, and then calls the corresponding factory.
class BaseFactory {
public:
static std::unique_ptr<Base> createObj(std::ifstream & file){
file.read((char *) specificTypeString, 2);//This isn't actually the code, just assume this part works
if(specificTypeString == "D2"){
return D2BaseFactory::createObj(file);
}
else if(specificTypeString == "D1"){
return D1BaseFactory::createObj(file);
}
else{
throw std::runtime_error("error");
}
}
};
With std::unique_ptr<Base> D1BaseFactory::createObj(std::ifstream & file);
returning std::unique_ptr<Derived1>(new Derived1(param1, param2, ...));
and the same thing for `D2BaseFactory'.
Problem is, if I construct a Derived class with the common BaseFactory
, and call pFunc()
on the returned unique_ptr, it always will be the empty Base::pStruct == {}
and thus trying to access members of the covariant pStructs isn't possible. I know this is because the factory createObj returns the base type, but is there any way to dynamically return the type I want so I can access the necessary fields in the derived pStructs? I think using raw pointers might work, but if possible i'd like to keep them as unique pointers.