gpt4 book ai didi

c++ - 不使用 RTTI 缓存不同派生类型的设计模式

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:04:43 25 4
gpt4 key购买 nike

假设我有一系列类都实现相同的接口(interface),可能用于调度:

class Foo : public IScheduler {
public:
Foo (Descriptor d) : IScheduler (d) {}
/* methods */
};

class Bar : public IScheduler {
public:
Bar (Descriptor d) : IScheduler (d) {}
/* methods */
};

现在假设我有一个 Scheduler 类,您可以要求为给定的描述符启动一个 IScheduler 派生类。如果它已经存在,您将获得对它的引用。如果不存在,则会创建一个新的。

一个假设的调用类似于:

Foo & foo = scheduler->findOrCreate<Foo>(descriptor);

实现它需要一个映射,其键(描述符,RTTI)映射到基类指针。然后你必须dynamic_cast。我猜是这样的:

template<class ItemType>
ItemType & Scheduler::findOrCreate(Descriptor d)
{
auto it = _map.find(SchedulerKey (d, typeid(ItemType)));
if (it == _map.end()) {
ItemType * newItem = new ItemType (d);
_map[SchedulerKey (d, typeid(ItemType))] = newItem;
return *newItem;
}
ItemType * existingItem = dynamic_cast<ItemType>(it->second);
assert(existingItem != nullptr);
return *existingItem;
}

想知道是否有人有办法在不依赖 RTTI 的情况下获得类似的结果。也许每个预定项目类型都可以有自己的 map 实例?一种设计模式,还是...?

最佳答案

函数或类静态成员的地址保证是唯一的(就< 而言),因此您可以使用这样的地址作为键。

template <typename T>
struct Id { static void Addressed(); };

template <typename ItemType>
ItemType const& Scheduler::Get(Descriptor d) {
using Identifier = std::pair<Descriptor, void(*)()>;

Identifier const key = std::make_pair(d, &Id<ItemType>::Addressed);

IScheduler*& s = _map[key];

if (s == nullptr) { s = new ItemType{d}; }

return static_cast<ItemType&>(*s);
}

请注意 operator[] 的使用避免重复查找并简化函数体。

关于c++ - 不使用 RTTI 缓存不同派生类型的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19597838/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com