令人难忘的工厂:何时实例化构造函数? [英] Unforgettable Factory: When is constructor instantiated?
问题描述
我正在实施令人难忘的工厂.一切正常,但有一件事:有时类未注册.
I'm implementing the unforgettable factory. Everything works fine but one thing: The classes are not registered, sometimes.
我认为关键部分是 Registrar::registered
成员.如果使用它,真正有趣的部分"将调用注册类的 registerT
函数.
I think the crucial part is the Registrar::registered
member. If it is used, "The really fun part" calls the registerT
function which registers the class.
在我的玩具示例中,除非有任何一种情况,否则课程不会被注册
In my toy example, the class is not registered unless either
- 构造函数已实现(在 cpp 文件中或内联中).显式默认构造函数和构造函数继承 (*) 不注册类.
- 基类(
Animal
)中有一个虚方法,它在注册类中被重写,并在cpp文件中实现.内联实现不起作用(与内联 ctor 不同).
- the constructor is implemented (in cpp-file or inline). Explicit default constructor and constructor inheritance (*) do not register the class.
- there is a virtual method in the base class (
Animal
), which is overridden in the registered class and implemented in cpp-file. Inline implementation does not work (unlike inline ctor).
是我弄错了还是作者遗漏了什么?在我的实际应用程序中,某些 类已注册,某些 类未注册,我无法发现差异(所有类都满足 (1.)),这就是我必须深化的原因我的理解.
Did I make a mistake or did the author miss something? In my real-world application, some classes are registered and some are not and I cannot spot the difference (all classes satisfy (1.)), that's why I must deepen my understanding.
我的问题是:registerT
究竟在什么情况下被调用?换句话说:Registrar
的构造函数什么时候实例化?我应该把 (void) 注册在哪里;
以便它总是实例化?
My question is: Under which circumstances exactly is registerT
called? In other words: When is the constructor of Registrar
instantiated?
Where should I put the (void) registered;
such that it is always instantiated?
(*) 为了使构造函数继承工作,我将 Factory
和 Factory<...>::Registrar
的构造函数设为 public
(*) to make constructor inheritance work, I made the constructors of Factory
and Factory<...>::Registrar
public
这个问题将我指向了令人难忘的工厂博文.这不是重复的.该问题的作者显然只是忘记添加真正有趣的部分"和关键的几乎空的构造函数.我没有忘记他们.我想知道为什么这个关键的几乎空的构造函数虽然存在但没有被实例化.
this question pointed me to the unforgettable factory blog post. This is not a duplicate. The author of that question apparently only forgot to add "The really fun part" and the crucial almost-empty-constructor. I didn't forget them. I want to know why this crucial almost-empty-constructor is not instantiated although it is there.
解决方案是不使用建议的模式.它似乎不适合生产代码,请参阅相关问题.>
The solution was not to use the proposed pattern. It does not seem to be fit for production code, see the relevant issue.
推荐答案
[basic.start.dynamic]/3非初始化 odr-use 是一种 odr-use (6.2),不是由初始化直接或间接引起的非局部静态或线程存储持续时间变量.
[basic.start.dynamic]/3 A non-initialization odr-use is an odr-use (6.2) not caused directly or indirectly by the initialization of a non-local static or thread storage duration variable.
[basic.start.dynamic]/4 静态存储期的非局部非内联变量的动态初始化是否在 main 或被推迟.如果它被延迟,它强烈发生在任何非内联函数或与要初始化的变量在同一翻译单元中定义的非内联变量的任何非初始化 odr 使用之前.
[basic.start.dynamic]/4 It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized.
这就是导致此和类似自注册计划失败的原因.有一个翻译单元包含实体的定义,这些实体的定义在程序的其他地方没有被引用,而只能由在同一翻译单元中定义的静态变量的初始值设定项引用.实现可能会选择推迟该静态变量的初始化,直到其翻译单元中的任何内容都被 odr 使用 - 这永远不会.
This is what causes this and similar self-registration schemes to fail. There's a translation unit containing definitions of entities that are not referenced elsewhere in the program, but only by the initializer of a static variable defined in that same translation unit. The implementation may choose to defer the initialization of that static variable until anything in its translation unit is odr-used - which is never.
这篇关于令人难忘的工厂:何时实例化构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!