我有一个模板类Foo
,它有一个方法barMethod
,它需要一个Bar
对象。我可以让每个Foo
对象根据需要创建Bar
对象,但是我不想这样做,因为它会很慢,而且很可能存在不同的Foo
对象可以使用相同的Bar
对象。
鉴于此,我想有一个BarManager
对象,该对象具有一组现有的Bar
对象。然后,Foo
对象可以向其请求Bar
对象,如果已经存在合适的对象,则管理器将简单地将其返回。如果没有,经理将创建一个新的并将其退回。
在我看来,实施“经理”方法存在两个问题。
BarManager
和Bar
都是模板类,因此即使我要使管理器成为全局变量/对象,也不确定如何工作。我想我可以将全局变量设置为void *,并在将其取消引用到适当的模板化类时将其强制转换,但这看起来确实很丑。必须有一种不那么丑陋的方法(也许使用auto
指针?)。什么事?
编辑:该软件是我(也许还有其他人)稍后将使用的库的一部分,这就是为什么对类进行模板化且模板类型未知的原因。另外,我想使Foo
的用户的操作尽可能简单,因此我不希望调用者对BarManager
或Bar
做任何事情(例如,实例化{{ 1}},并引用每个BarManager
)。
答案 0 :(得分:3)
如果您:
BarManager
的具体类型。然后,您可以让所有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;
}
答案 1 :(得分:0)
关于如何引用BarManager
的方法有两种:
main()
/ singleton / monostate中局部对象的全局指针。优点是易于访问。BarManager
的实例。好处是您可以有许多BarManager
对象。缺点是必须将额外的参数传递给调用,尤其是在调用链很深和/或必须将对其的引用/指针存储为成员变量的情况下。答案 2 :(得分:0)
因此,您需要负责构造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); }
};