c++ - unique_ptr 的自定义克隆不返回正确的类型
问题描述
我有这两个类:
class Operation {
public:
virtual std::unique_ptr<Operation> clone() = 0;
};
class Plus : public Operation {
public:
std::unique_ptr<Operation> clone() override {
return std::make_unique<Plus>(*this);
};
};
我有这个函数,它检查函数的类型:
template<typename Base, typename T>
inline bool instanceof(const T*) {
return std::is_base_of<Base, T>::value;
}
我的克隆方法遇到问题,在我克隆对象后它没有通过我的实例。
std::unique_ptr<SweCpp::Upn::classesforOp::Plus> p1 = std::make_unique<SweCpp::Upn::classesforOp::Plus>();
auto p2 = p1->clone();
if(!instanceof<SweCpp::Upn::classesforOp::Plus>(p2.get())) return false;
return true;
此检查失败,因为我返回了一般类型,unique_ptr<Operation>
而不是unique_ptr<Plus>
在我的克隆方法中。如何更改我的克隆,使其返回子类,而不是我的接口类Operation
?
解决方案
您的模板参数是向后的。您设置Base
为Plus
,并T
推断为Operation
。因此,您调用std::is_base_of<Plus, Operation>::value
的总是错误的,因为Plus
它不是Operation
. 反之亦然,Operation
是基数Plus
。所以交换模板参数:
template<typename T, typename Base>
inline bool instanceof(const Base*) {
return std::is_base_of<Base, T>::value;
}
现在,话虽如此,这instanceof()
仍然没有做正确的事情。std::is_base_of
是编译时检查,但您不能在编译时检查多态对象类型,因为编译器不知道基指针实际指向的派生类型。它只知道指针本身的类型。
假设您定义了另一个类,该类Plus
也派生自Operation
,然后将该其他类的克隆传递给您的版本instanceof()
,std::is_base_of<Operation, Plus>::value
即使该对象实际上不是 的实例,它仍然为真Plus
。
为了解决这个问题,您需要在运行时dynamic_cast
检查对象类型,例如:
template<typename T, typename Base>
inline bool instanceof(const Base *b) {
return dynamic_cast<const T*>(b) != nullptr;
}
推荐阅读
- excel-formula - 具有多列和多行的复杂索引/匹配
- python - Spyder 找不到名为“pandas_datareader”的模块
- ruby-on-rails - Rails 博客的投票系统,在投票前设计用户登录
- git - git read-tree 如何在没有 -m 或 --reset 选项的情况下工作
- reactjs - 如何在反应中从输入字段中删除绿色?
- java - 另一个 javafx 程序中的 javafx 程序
- c# - 从列表中查找未完成任务的详细信息
- amazon-web-services - ECS 服务 aws-cli 与仪表板
- ios - 使用 Swift 和 Objective-C 时与领域“大小”对象的名称冲突
- python - Python - 关于登录 __init__.py 的问题