我试图在我的C ++应用中实现用户默认值。 为此,我创建了一个包含一个函数的接口类:
class IRegisterUserDefaults
{
public:
IRegisterUserDefaults();
virtual void registerUserDefaults(){}
};
从这个接口类继承的每个类都将实现注册需要设置的用户默认值的函数。
到目前为止没问题。但是最好的方法是什么? 我来自Objective-C,在那里我可以搜索所有类,找到实现接口的人并在其上调用registerUserDefaults函数。我理解C ++并没有这种内省水平。每个类调用一次函数就足够了(从而使它成为静态函数)。
目标
如果函数被调用"自动"那将是很好的。如果一个类是IRegisterUserDefaults的子类。我尝试从IRegisterUserDefaults构造函数调用该方法,但看起来这并没有正确调用子类函数。有没有办法让这种情况发生?
此外,最好的方法是确保每个课程只调用一次?
答案 0 :(得分:2)
IRegisterUserDefaults
不是一个有意义的界面,用任何语言。
这听起来像你要解决的实际问题是"运行一些代码,在第一次使用时或附近运行#34;。你可以用这样的东西做到这一点
class HasUserDefaults {
static std::once_flag register_once;
void registerUserDefaults() { /*...*/ }
public:
HasUserDefaults ()
{
// in all the constructors
std::call_once(register_once, &HasUserDefaults::registerUserDefaults, this);
}
// other members
};
答案 1 :(得分:1)
这对你有用吗?
#include <iostream>
#include <string>
class IRegisterUserDefaults
{
public:
IRegisterUserDefaults() {}
virtual void registerUserDefaults() = 0;
};
class MoreDerivedRegisterUserDefaults : public IRegisterUserDefaults
{
public:
MoreDerivedRegisterUserDefaults (int x, int y) : m_x (x), m_y (y) { }
virtual void registerUserDefaults() override {
std::cout << "MoreDerivedRegisterUserDefaults::registerUserDefaults called (" << m_x << ", " << m_y << ")" << std::endl;
}
private:
int m_x, m_y;
};
template <class T, typename... Args> void RegisterDefaultsHandler (Args... args) {
T obj (args...);
obj.registerUserDefaults ();
}
int main ()
{
RegisterDefaultsHandler<DerivedRegisterUserDefaults> ();
RegisterDefaultsHandler<MoreDerivedRegisterUserDefaults> (1, 2);
// ...
}
您必须在某处实例化每个派生类。
直播demo(已更新)。输出:
DerivedRegisterUserDefaults::registerUserDefaults called
MoreDerivedRegisterUserDefaults::registerUserDefaults called (1, 2)
编辑:在与@Caleth交谈后,我稍稍调整了一下代码,以使我的意图更清晰。
编辑2:添加了Variadiac模板,结果比我想象的更容易,有用'howto'指南here。
答案 2 :(得分:1)
您是否只有一个位置可以知道所有派生类?在那种情况下,在那里做:
// The type-list can be used in many ways, as you need
using all_classes = std::tuple<A, B, C, D /* and so on */>;
template <class... Ts>
static void register_all_classes(Y<Ts...>*)
{ ((Ts().registerUserDefaults()), ...); }
register_all_classes((all_classes*)nullptr);
否则,你显然必须分散:
您是否有一个负责注册每个班级的编译单位?在这种情况下,请使用命名空间范围对象。也许可以使用帮助器:
template <class T>
struct Init {
Init() { T().registerUserDefaults(); }
};
// Used in single TU as:
static Init<SomeRegisterUserDefaults> _;
否则,请查看std::ios_base::Init
<iostream>
如何做到template <class T>
struct MultiInit {
MultiInit() { static Init<T> _; }
};
// Used in any number of TUs as:
static MultiInit<SomeRegisterUserDefaults> _;
。我简化了,因为没有必要指出:
GET
答案 3 :(得分:0)
在子类构造函数中调用该方法,你不能在基类构造函数中调用它,因为那时尚未构造子类。