C++ 协变参数 - 设计模式

标签 c++ polymorphism covariance contravariance

以下面简化的 C++ 类层次结构为例。我想要完成的是 Service 提供一个虚拟方法来保存任意 Model 对象。但是 Service 的每个子类,例如BoxService 应该而且只能保存 Box 对象。

由于 C++ 不支持方法参数中的协变,我无法简单地在 BoxService.h 中声明 save 方法,如下所示:

void save(Box box);

我的问题是,对于这个问题是否有任何首选的设计模式或最佳实践?或者如果到达的 Model 对象是 Box 类型,我应该检查 BoxService.cpp 中保存函数的实现,否则抛出异常?

模型.h

class Model {
private:
    int id;
};

Box.h

class Box : public Model {
private:
    int size;
};

Service.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) {}
};

模型定义为变体而不是继承层次结构:

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/

相关文章:

c++ - C++ 大数快速排序堆栈溢出

c++ - 避免使用内联 asm 优化 away 变量

c++ - 我应该使用多个 Vectors 还是 Enum 状态

java - 我如何限制使用它们的子类的抽象类中的方法参数?

支持加权协方差计算的Python包

c++ - 如何为cuda编程设置visual studio 2005

C++ 多重继承从文件保存对象中读取两次

java - 如何使父类(super class)中的某些方法在子类中不可用

c++ - 对于迭代器和类似情况应该如何处理 'Invalid covariant return types'

c++ - 为什么智能指针 vector 不是指向实现与该接口(interface)协变的接口(interface)的项目?