作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
以下面简化的C++类层次结构为例。我想要完成的是 Service
提供了一个用于保存任意 Model
对象的虚拟方法。但是 Service
的每个子类,例如BoxService
应该并且只能保存 Box
对象。
由于 C++ 不支持方法参数中的协变,我不能简单地在 BoxService.h
中声明保存方法,例如:
void save(Box box);
我的问题是,是否有针对该问题的首选设计模式或最佳实践?或者,如果到达的模型对象是 Box 类型,我是否应该在 BoxService.cpp
中检查保存函数的实现,否则抛出异常?
模型.h
class Model {
private:
int id;
};
Box.h
class Box : public Model {
private:
int size;
};
服务.h
class Service {
public:
virtual void save(Model model);
};
BoxService.h
class BoxService : public Service {
public:
void save(Model box);
};
BoxService.cpp
void BoxService::save(Model box) {
// TODO: save box and make sure that box is of type 'Box' and not any other subtype of 'Model'
}
最佳答案
这也许是一个更实用的方法:
将每种模型类型与其实现配对:
template<typename T, typename ExtraType>
struct WithType {
T value;
using extra_type = ExtraType;
WithType(T value) : value(value) {}
};
将 Model
定义为变体而不是继承层次结构:
using Model = std::variant<WithType<Box, BoxService>, WithType<X, XService>>;
现在访问变体:
class Service {
public:
void save(Model m) const {
visit([](auto withService) {
typename decltype(withService)::extra_type service;
service.save(withService.value);
}, m);
}
void remove(Model m) const {
visit([](auto withService) {
typename decltype(withService)::extra_type service;
service.remove(withService.value);
}, m);
}
};
关于C++ 协变参数 - 设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42867996/
在我的设置中,我试图有一个界面 Table继承自 Map (因为它主要用作 map 的包装器)。两个类继承自 Table - 本地和全局。全局的将有一个可变的映射,而本地的将有一个只有本地条目的映射。
Rust Nomicon 有 an entire section on variance除了关于 Box 的这一小节,我或多或少地理解了这一点和 Vec在 T 上(共同)变体. Box and Vec
我是一名优秀的程序员,十分优秀!