c++ - 访问派生类的方法协变返回,派生自带有 unique_ptr 的工厂构造
问题描述
编辑:我的问题可能只是问如何降低 aunique_ptr<base>
到unique_ptr<derived>
(已经回答),但我不是 100% 确定我在问什么
我有一个抽象基类Base
class Base{
public:
Base();
struct pStruct{};
virtual pStruct pFunc(std::vector<double> data) = 0;
protected:
CustomType dataValue;
};
和两个派生类Derived1
并Derived2
实现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;
};
调用类方法pFunc(std::vector<double> data)
时,每个派生类将返回不同的类型和数量的值。我尝试使用协变返回类型进行这项工作,因此Derived1::predict(data).key1
可能是矩阵,也.key2
可能是其他东西,依此类推。Derived2::predict(data).key1
可能是唯一的键,它可能是一个布尔值。每个派生类都定义了自己的::predict()
返回字段,因为它们差异很大。
问题是,我用一个工厂构造这些派生类,它读取一些输入(通过 ifstream 构造),并找出它应该是什么派生类,然后调用相应的工厂。
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");
}
}
};
对于“D2BaseFactory”std::unique_ptr<Base> D1BaseFactory::createObj(std::ifstream & file);
返回和相同的东西。std::unique_ptr<Derived1>(new Derived1(param1, param2, ...));
问题是,如果我用 common 构造一个 Derived 类BaseFactory
,并调用pFunc()
返回的 unique_ptr,它总是为空的Base::pStruct == {}
,因此无法访问协变 pStructs 的成员。我知道这是因为工厂 createObj 返回基本类型,但是有没有办法动态返回我想要的类型,以便我可以访问派生 pStructs 中的必要字段?我认为使用原始指针可能会起作用,但如果可能的话,我想将它们保留为唯一指针。
解决方案
你可以做类似这样的事情:
class Base
{
public:
...
std::unique<pStruct> pFunc(...) { return DopFunc(); }
protected:
virtual std::unique<pStruct> DopFunc() = 0;
};
class Derived1 : public Base
{
public:
struct pStructD1 : Base::pStruct { ... };
// Used when calling the child factory directly...
std::unique_ptr<pStructD1> pFunc(...)
{
return std::make_unique<pStructD1>(...);
}
protected:
// Used when called through the Base factory...
std::unique<pStruct> DopFunc(...) override
{
// Call the other function for code sharing... (DRY)
return pFunc(...);
}
....
};
如果您在需要派生对象时使用派生类,这可能是有意义的。
真正的问题是为什么你需要使用派生类型......如果它是出于初始化目的,那么也许工厂应该在返回值之前执行它。
如果是为了一些处理,那么也许你应该在pStruct
. 这样,您永远不需要知道工厂返回的派生类型。
在某些情况下,访问者模式也可能是一种解决方案。
如果您需要始终使用特定的结构,那么为什么不总是使用特定的工厂呢?
您也可以转换结果,但如果您每次创建对象时都需要这样做,它可能会使代码变得更复杂。
或者,你也可以有一个模板成员函数 let say template <class T> std::unique_ptr<T> pFuncT(...) { ... }
。这样,客户端代码可以直接在构造时指定所需的类型。如果类型不正确,可能会引发空对象或异常。
推荐阅读
- android - 我可以为两个项目使用一个 mysql 数据库吗?
- pascal - 从函数返回字符串 (VAX PASCAL)
- reactjs - 无法打开新的弹出窗口反应引导
- django - 如何从模型中获取字段值
- python - 如何在 Paramiko 中使用 SFTP 更新服务器中的文件
- python - 如何从熊猫数据框列中提取信息
- python - 如何使我的 tkinter 图像弹出不显示 tkinter 选项窗口
- c# - 您如何将徽标放在您的 CrystalReport 上的页眉中?
- javascript - 在 hls.js / Video.js 中进行视频质量控制以进行实时流式传输
- android - 按下设备主页按钮时不会关闭 Android 生物识别提示