[英]Unforgettable Factory and multiple levels of inheritance and hierachy
我一直在試驗這里描述的工廠實現:
http://www.nirfriedman.com/2018/04/29/unforgettable-factory/
該示例使用“Animal”作為基礎,使用“Dog”和“Cat”作為在工廠注冊的派生類。 但是現在假設我想添加一個派生自 Cat 的“Lion” class ......我如何在仍然向 Animal factory 注冊的同時從 Cat 派生? 此外,我還希望能夠創建一個“Cat”工廠,它可以讓我創建類型為“Cat”而不是“Animal”的 object。 這個例子可以適應這樣做嗎?
這是一些基於原始帖子的代碼,顯示了我正在嘗試做的事情。
#include <functional>
#include <memory>
#include <exception>
#include <iostream>
#include <string>
#include <map>
#include <unordered_map>
#include <cstdlib>
#include <cxxabi.h>
template<typename BaseT, typename ...Args>
class Factory
{
public:
friend BaseT;
template<class ...T>
static std::shared_ptr<BaseT> create(const std::string& name, T&&... args)
{
try
{
return types().at(name)(std::forward<T>(args)...);
}
catch(std::out_of_range e)
{
throw std::runtime_error("type \"" + name + "\" is not registered with the factory");
};
};
template<typename T>
struct Registrar : BaseT
{
public:
friend T;
static bool register_type()
{
auto demangle = [](const char* name) -> std::string
{
int status = -4;
std::unique_ptr<char, void (*)(void *)> res{abi::__cxa_demangle(name, NULL, NULL, &status), free};
return (status == 0) ? res.get() : name;
};
const auto name = demangle(typeid(T).name());
std::cout << "registering " << name << "\n";
Factory::types()[name] = [](Args... args) -> std::shared_ptr<BaseT>
{
return std::make_shared<T>(std::forward<Args>(args)...);
};
return true;
};
static inline bool registered = register_type();
private:
Registrar() : BaseT() { (void) registered; };
};
private:
using FunctionT = std::function< std::shared_ptr<BaseT>(Args...)>;
static auto& types()
{
static std::unordered_map<std::string, FunctionT> m_types;
return m_types;
};
};
struct Animal : Factory<Animal>
{
virtual void speak() = 0;
virtual ~Animal() = default;
};
// How can I create a Cat factory at this level in the hierarchy?
class Cat : public Animal::Registrar<Cat>
{
public:
Cat() {};
virtual ~Cat() = default;
virtual void speak() { std::cout << "Meow!" << "\n"; };
};
// I would like to register Lion with the Animal factory.
class Lion : public Cat
{
public:
Lion() {};
void speak() { std::cout << "Roar!" << "\n"; };
};
int main(int argc, char** argv)
{
auto a = Animal::create("Cat");
a->speak();
auto lion = Cat::create("Lion"); // this doesn't work
lion->speak();
return 0;
};
我最終通過從Registrar
器 class 的Base
中刪除 inheritance 來稍微調整工廠 class。 我改變了這個:
template <class T> struct Registrar : Base {
對此:
template <class T> struct Registrar
回到我上面的例子,我現在像這樣使用工廠:
struct Animal
{
virtual void speak() = 0;
virtual ~Animal() = default;
};
using AnimalFactory = Factory<Animal>;
struct Cat : public Animal, public AnimalFactory::Registrar<Cat>
{
<snip>
};
struct Lion : public Cat, public AnimalFactory::Registrar<Lion>
{
<snip>
};
主要區別在於現在每個 class 都必須派生自Animal
class 或子類以及AnimalFactory::Registrar
類型。 它有點冗長,但我現在可以使用具有多個級別的 inheritance 的工廠。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.