在从给定超类继承的所有类上调用虚函数
Calling a virtual function on all classes inheriting from a given superclass
我正在尝试在我的C++应用程序中实现用户默认值。 为此,我创建了一个包含一个函数的接口类:
class IRegisterUserDefaults
{
public:
IRegisterUserDefaults();
virtual void registerUserDefaults(){}
};
从此接口类继承的每个类都将实现该函数来注册需要设置的用户默认值。
到目前为止没有问题。但是最好的称呼方式是什么? 我来自Objective-C,在那里我可以搜索所有类,找到实现接口并在其上调用registerUserDefaults函数的类。我知道C++没有这种程度的内省。每个类调用一次函数就足够了(从而使它成为静态函数(。
目的
如果一个类子类 IRegisterUserDefaults 时"自动"调用该函数,那就太好了。我尝试从 IRegisterUserDefaults 构造函数调用该方法,但看起来这不能正确调用子类函数。有没有办法做到这一点?
另外,确保每个类只调用一次的最佳方法是什么?
IRegisterUserDefaults
在任何语言中都不是一个有意义的界面。
听起来您尝试解决的实际问题是"在类首次使用时或接近类时运行一次代码"。你可以用这样的东西来做到这一点
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
};
您是否有一个已知所有这些派生类的位置?在这种情况下,请在此处执行:
// 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>
是如何做到的。我简化了,因为不需要 uninit 指示:
template <class T>
struct MultiInit {
MultiInit() { static Init<T> _; }
};
// Used in any number of TUs as:
static MultiInit<SomeRegisterUserDefaults> _;
这对你有用吗?
#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);
// ...
}
您必须在某处实例化每个派生类。
现场演示(更新(。 输出:
DerivedRegisterUserDefaults::registerUserDefaults called
MoreDerivedRegisterUserDefaults::registerUserDefaults called (1, 2)
编辑:在与@Caleth交谈后,我对代码进行了一些调整,以使我的意图更加清晰。
编辑2:添加了Variadiac模板,结果比我想象的要容易,有用的"操作方法"指南在这里。
在子类构造函数中调用该方法,不能在基类构造函数中调用此方法,因为那时子类尚未构造。
- 如何用参数值调用函数(仅在运行时已知)
- 从python中调用C++函数并获取返回值
- 当使用通配符和null指针调用函数时,对输出的说明
- 从R调用C++函数并对其进行集成时出错
- 使用QTreeView,如何通过调用函数只突出显示特定的行/列
- 如何在qt中从另一个类调用函数
- 在 COUT 语句中使用 COUT 调用函数
- 如何从线程中的不同模块调用函数?
- C++从函数指针数组调用函数
- 当 A 在 for 循环中调用函数 B 时,如何计算函数 A 的空间复杂度?
- 如何在 C/C++ 中从外部库调用函数
- 如何使用运算符在同一行中多次调用函数
- 是否可以创建一个从不同类调用函数的线程?
- 无法为类成员调用函数
- 如何从另一个标头 c++ 调用函数
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 如何只允许在调用函数 B 后调用函数 A?
- 我可以这样调用函数吗?
- 如何在 c++ 的类中递归调用函数方法?
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?