共享的从属对象

Shared subservient object

本文关键字:对象 共享      更新时间:2023-10-16

我有一个模板类Foo,它有一个方法,barMethod,需要一个Bar对象。 我可以根据需要让每个单独的Foo对象创建Bar对象,但我不想这样做,因为它会很慢,并且不同的Foo对象很有可能使用相同的Bar对象。

鉴于此,我希望有一个具有现有Bar对象集的BarManager对象。 然后,Foo对象可以向它请求Bar对象,如果已经存在适当的对象,管理器将简单地返回它。 如果没有,经理将创建一个新的并返回它。

在我看来,实施"经理"方法有两个问题。

  1. 管理器必须是一个全局变量,我宁愿不这样做。
  2. BarManagerBar都是模板类,所以即使我要使管理器成为全局变量/对象,我也不确定它是如何工作的。 我想我可以将全局变量设为 void * 并在取消引用到适当的模板化类时强制转换它,但这似乎真的很丑陋。

必须有一种不那么丑陋的方法(也许使用auto指针? 这是什么?

编辑:该软件是我(也许还有其他人(稍后将使用的库的一部分,这就是为什么类是模板化的并且模板类型不是先验已知的。 另外,我想让Foo的用户尽可能简单,所以我不希望调用者必须对BarManagerBar做任何事情(例如,实例化BarManager并为每个Foo提供引用(。

如果您:

  1. 在编译时了解BarManager的具体类型。
  2. 不希望Foo的任何用户知道这种内部机制。

然后,您可以让所有Foo类将此BarManager作为static保存(绝对不是全局变量(

template <typename T>
class Bar{};
template <typename T>
class BarManager;
template <typename T>
class Foo
{
private:
static BarManager<T>& GetBarManager()
{
static BarManager<T> managerInstance;
return managerInstance;
}
public:
void barMethod()
{
auto& bar = GetBarManager().GetBarInstance();
// Do something with `bar`
}
};
template <typename T>
class BarManager
{
public:
Bar<T>& GetBarInstance()
{
// Replace with cacher implementation:
static Bar<T> dud;
return dud; 
}
};
int main()
{
Foo<int> foo;
foo.barMethod();
return 0;
}

关于如何引用BarManager有两种选择:

  1. 将其作为全局对象/指向main()/单例/单状态中的本地对象的全局指针。优点是易于访问。
  2. 显式传递指向BarManager实例的指针/引用。优点是可以有许多BarManager对象。缺点是必须将额外的参数传递给调用,特别是如果调用链很深和/或必须将指向它的引用/指针存储为成员变量。

所以你需要任何负责构造Foo的东西,首先构造所有BarManager,然后将它们传递到构造Foo。由于我真的不知道具体细节,我不得不把它留给你,但给出一个简单的:template<typename T> struct Bar { using value_type = T; const T _val; };你的BarManager骨架可能看起来像这样:

template<typename T>
class BarManager {
vector<shared_ptr<Bar<T>>> _bars;
public:
using value_type = T;
size_t size() { size(_bars); }
shared_ptr<Bar<T>>& get_bar(const T target) {
const auto it = find_if(begin(_bars), end(_bars), [&](const shared_ptr<Bar<T>>& i) { return i->_val == target; });
if(it == end(_bars)) {
_bars.push_back(make_shared<Bar<T>>(target));
return _bars.back();
} else {
return *it;
}
}
};

从那里,您的Foo可能如下所示:

template<typename T>
class Foo {
shared_ptr<BarManager<T>> _my_manager;
shared_ptr<Bar<T>> _my_bar;
public:
using value_type = T;
Foo(shared_ptr<BarManager<T>>& my_manager) : _my_manager(my_manager) {}
void request_bar(const T& target) { _my_bar = _my_manager->get_bar(target); }
};