为啥我应该使用 DECLARE_DYNAMIC 而不是 DECLARE_DYNCREATE?

Posted

技术标签:

【中文标题】为啥我应该使用 DECLARE_DYNAMIC 而不是 DECLARE_DYNCREATE?【英文标题】:Why should I use DECLARE_DYNAMIC instead of DECLARE_DYNCREATE?为什么我应该使用 DECLARE_DYNAMIC 而不是 DECLARE_DYNCREATE? 【发布时间】:2015-01-10 18:27:29 【问题描述】:

DECLARE_DYNCREATE 提供与 DECLARE_DYNAMIC 完全相同的功能以及动态对象创建能力。那么为什么有人应该使用 DECLARE_DYNAMIC 而不是 DECLARE_DYNCREATE?

【问题讨论】:

反对票是不正当的。实现的特殊性是可以理解的混淆来源。这是一个试图学习做正确事情的人。如果您认为这不是一个好问题,请不要投赞成票。 这是一个很好的具体问题。投票者很可能不是实际使用 Visual C++ 和使用 Visual C++ 进行编程的人,而只是 *** 清道夫,因为多年来,我们大多数 *** 人实际上以工作为生,已经习惯了这种做法。 例如,请参阅这个几乎相同的问题:***.com/questions/733717/…。这个问题来自 2009 年,有很多赞成票,没有反对票。这个问题来自 2009 年,没有反对意见,这并非巧合。 2009 年,成群的 *** downvote 和 close-vote 清道夫还没有出现。 【参考方案1】:

记录宏以提供不同的功能。

DECLARE_DYNAMIC:

在从 CObject 派生类时,添加了访问有关对象类的运行时信息的功能。

这提供了自省功能,类似于 C++ 提供的 RTTI (Run-Time Type Information)。应用程序可以通过关联的CRuntimeClass Structure 查询CObject 派生类实例的运行时类型。它在您需要检查对象是否属于特定类型或具有特定基类类型的情况下很有用。 CObject::IsKindOf 的示例应该会给你一个好主意。

DECLARE_DYNCREATE:

使 CObject 派生类的对象能够在运行时动态创建。

此宏允许在运行时动态创建类实例。该功能是通过类工厂方法CRuntimeClass::CreateObject 提供的。当您需要在运行时根据类类型的字符串表示创建类实例时,可以使用它。一个示例是可自定义的 GUI,它是从初始化文件构建的。

这两个功能都是通过相同的CRuntimeClass Structure 实现的,这可能会导致它们可以互换使用的结论。事实上,使用不适当宏的代码将编译得很好,并公开所需的运行时行为。区别纯粹是语义上的:宏传达不同的意图,应根据所需的功能使用,以传达开发者的意图。

还有第三个相关的宏,DECLARE_SERIAL

生成可序列化的CObject派生类所需的 C++ 标头代码。

它启用了各个CObject 派生类实例的序列化,例如文件、内存流或网络套接字。由于反序列化过程需要从序列化流中动态创建对象,因此它包含了DECLARE_DYNCREATE 的功能。

综合起来,以下列表应该可以帮助您为特定场景选择正确的宏:

    如果您的代码需要检索对象的运行时类型,请使用 DECLARE_DYNAMIC。 如果您需要根据类型的字符串表示动态创建类实例,请使用DECLARE_DYNCREATE。 如果您还需要提供序列化支持,请使用DECLARE_SERIAL

【讨论】:

另外注意,如果你在头文件中使用DECLARE_DYNCREATE,你必须确保在源文件中匹配IMPLEMENT_DYNCREATE。 (其他人也一样。)【参考方案2】:

您是在问“我拥有平头螺丝刀,为什么还要买十字螺丝刀?”答案是您应该使用适合您需要的工具:如果您只需要驱动平头螺钉,请不要购买十字螺丝刀。否则,买一个。

如果您需要DECLARE_DYNCREATE 提供的功能(例如,因为您正在创建一个在打开文档时由框架自动创建的视图),那么您应该使用DECLARE_DYNCREATE,如果您不需要并且@ 987654323@ 有效,你应该使用它。

【讨论】:

以上是关于为啥我应该使用 DECLARE_DYNAMIC 而不是 DECLARE_DYNCREATE?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我应该使用 Any 方法而不是 Count? [复制]

Android:何时/为啥我应该使用 FrameLayout 而不是 Fragment?

为啥我应该使用 LoadBalancerProbe 而不是订阅 RoleEnvironment.StatusCheck 事件?

为啥我应该使用 CString 的 GetBuffer 成员而不是 SetAt?

为啥我应该使用 char 而不是 varchar? [复制]

为啥我不应该包含 cpp 文件而使用标头?