具有派生类实例的工厂

问题描述 投票:0回答:2

我有一种奇怪的用例。这是一个非常简化的版本。

假设我有一个类Base和类DerivedOneDerivedTwo,它们来自Base类。

然后,有一个枚举:

enum DerClasses {Derived1, Derived2};

和一个函数,它将获取枚举并返回派生类的实例,具体取决于值。

就像是:

inline Base* create_instance(DerClasses enum_class){
    switch(enum_class) {
        case Derived1:
            return new Derived1();
        case Derived2:
            return new Derived2();
    }
}

显然这是有效的,但只有随后转换为派生类。

Derived1 *derived_pointer = dynamic_cast<Derived1*>(pointer);

而且我不希望用户自己制作这些动态演员表,甚至不知道有关这些类的任何信息。

是否可能以某种方式隐藏这些强制转换并使用自动类型演绎制作API,例如

auto ptr = create_instance(DerClasses::Derived1);
ptr->derived1_class_only_variable = 123;
c++ c++11 inheritance design-patterns polymorphism
2个回答
3
投票
template<DerClasses enum_class>
auto create_instance(){
  if constexpr (enum_class == DerClasses::Derived1) {
    return std::make_unique<Derived1>();
  else if constexpr (enum_class == DerClasses::Derived2) {
    return std::make_unique<Derived2>();
}

这就像。在这样做非常烦人。

如果你在编译时不知道DerClasses值,这不起作用,并且无法工作。你最接近的是延续传递风格:

template<class F>
decltype(auto) create_instance(DerClasses enum_class, F&& f){
  switch(enum_class) {
    case DerClasses::Derived1:
      return f(std::make_unique<Derived1>());
    case DerClasses::Derived2:
      return f(std::make_unique<Derived2>());
  }
}

使用如下:

create_instance(DerClasses::Derived1, [&](auto&& ptr) {
  if constexpr( std::is_same< std::decay_t<decltype(*ptr)>, Derived1 >{} )
    ptr->derived1_class_only_variable = 123;
});

但这也很糟糕,因为lambda是用两种派生类型调用的;只运行一个。

使用覆盖可以起作用,但你又疯了。


2
投票

你可以通过一些元编程来实现。如果您使用的是C ++ 11/14,可以执行以下操作:

enum class ClassType {
    FirstType,    
    SecondType,
    ThirdType
};

 namespace internal {

    template <ClassType Type>
    struct _build_type {};

    template <>
    struct _build_type<ClassType::FirstType> {
        constexpr auto operator()() {
            return std::make_unique<MyFirstType>();
        }
    };

    template <>
    struct _build_type<ClassType::SecondType> {
        constexpr auto operator()() {
            return std::make_unique<MySecondType>();
        }
    };

    template <>
    struct _build_type<ClassType::ThirdType> {
        constexpr auto operator()() {
            return std::make_unique<MyThirdType>();
        }
    };

} 

template <WindowType Type>
constexpr auto create_instance() {
    return internal::_build_type<Type>{}();
}

然后你的代码就变成了你所说的:

auto ptr = create_instance<ClassType::FirstType>();
ptr->derived1_class_only_variable = 123;

在现代C ++ 17中,您可以使用简单的constexpr if条件简化代码。

© www.soinside.com 2019 - 2024. All rights reserved.