delphi 当有问题的类在编译和链接时就存在,并且显式地存在于代码中时,在运行时引发的EClassNotFound真正意味着什么?

ogq8wdun  于 2022-11-04  发布在  其他
关注(0)|答案(6)|浏览(141)

在执行TReader.ReadRootComponent时,我在表单的rtl流中发生了一个运行时错误,导致引发了异常EClassNotFound。具体的错误消息是“找不到类TActionList”。
奇怪的是:
1.我的主窗体使用动作列表。
1.为了好玩,我将ActnList.pas(来自VCL源文件夹)添加到我的项目中,以尝试修复它。
在示例化一个几分钟前还在工作的表单时,我遇到了这种情况。我所做的更改是在一些子帧代码中:我用ifdef标记删除了它的所有实现部分代码,因为我模拟了一些框架,用于单元测试和原型。
我试着将动作列表类添加到项目中,我试着使用和不使用各种编译器和链接选项,但是,我仍然得到了这个异常。显然,发生了一些奇怪的事情。一定有其他奇怪的方法来得到这个问题。
实际上,似乎有一些非常奇怪的事情正在发生。当这个错误被引发时,我得到了下面的调用堆栈:

rtl.Classes.ClassNotFound('TActionList')
rtl.Classes.TReader.FindComponentClass(???)
rtl.Classes.FindExistingComponent
rtl.Classes.TReader.ReadComponent(nil)       /// NIL!? WHAT!!!!!
rtl.Classes.TReader.ReadDataInner(???)
rtl.Classes.TReader.ReadData(???)
rtl.Classes.TComponent.ReadState(???)
vcl.Controls.TControl.ReadState(???)
vcl.Controls.TWinControl.ReadState($60B9CF0)
vcl.Forms.TCustomForm.ReadState(???)
rtl.Classes.TReader.ReadRootComponent($606EB90)
rtl.Classes.TStream.ReadComponent($606EB90)
rtl.Classes.InternalReadComponentRes(???,???,$606EB90)
rtl.Classes.InitComponent(TComplexFormContainingFrames)

在TReader.ReadDataInner(示例:TComponent)中,nil似乎是有意的:

while not EndOfList do ReadComponent(nil);

**更新:**我相信这个问题的答案是理解Mason提到的“序列化上下文”。现在是时候承认我自己的愚蠢了:我从项目中删除了框架的父级,没有意识到它是框架的父级。我通过将TMyFrameParent的类型声明替换为TMyFrameParent = class(TFrame)来解决它的缺失,这反过来又导致了问题中的条件。我将问题留在这里,因为我认为将来在神秘的情况下发生这种异常时,注意到它可能真的很方便。以及如何修复它。特别是,Mason有一些关于“序列化上下文”以及它们如何应用于类名查找的非常有趣的信息。

bmp9r5qi

bmp9r5qi1#

这意味着在当前反序列化上下文中找不到该类。并非所有现有类都为所有加载注册。每个窗体类都有RTTI,其中包含对它所使用的组件的引用。要使其正常工作,请确保您的窗体(或框架,如果这是一个框架)在private标记之前至少声明一个TActionList:

TMyForm = class(TForm)
  ActionList: TActionList;
  OtherComponent: TSomeComponent;
private
  //whatever
public
  //whatever
end;
bqucvtff

bqucvtff2#

使用Classes.RegisterClass来注册您希望在流媒体系统中使用的类。
在表单声明(示例变量)中引用的表单类和组件类将自动注册。如果要保存示例,则应用程序使用的任何其他类都必须通过调用RegisterClass显式注册。一旦注册了类,组件流系统就可以加载或保存这些类。

ohfgkhjo

ohfgkhjo3#

当你从一个项目复制一个帧到另一个项目时,似乎会发生这种情况,而那个帧继承了某个东西,你假装继承,但在帧dfm中留下“继承”的项目描述,项目如下:

inherited ActionList: TActionList
  Left = 520
  Top = 576
end

这反过来又导致了Mason所说的“当前反序列化上下文”,不包含类。一个修复方法是在上述所有情况下将Inherited更改为object。

vatpfxk5

vatpfxk54#

出现此错误的另一种方法是:将“public”放在窗体定义类的顶部。默认情况下,类成员是“published”。我不小心将“public”添加到窗体声明的顶部,这在运行时产生了多个“Class not found”异常。

cnh2zyt3

cnh2zyt35#

当我的DFM文件中有一个TLabel声明,但是在相应的PAS文件中没有它的声明时,我得到了一个“EClassNotFound”错误。不知何故,表单编辑器搞砸了。
直到我删除了表单中的所有标签,除了那个“损坏”的标签,这个错误才被发现。很难找到它,因为那个标签被隐藏在面板下面。
一个简单的解决方法是从表单中剪切(ctrl+x)该标签(一旦找到它)并将其粘贴回去。这次表单编辑器将正确地在PAS文件中插入它的声明。

qmelpv7a

qmelpv7a6#

还有另一种方法可以得到这个错误:我已经将'private'放在表单定义类的顶部(因为没有任何元素在表单之外使用)。
因此,与前面的答案相同(Server Overflow):默认情况下,类成员是“已发布”的,如果您更改窗体声明的可见性,则会在运行时产生多个“找不到类”异常。

相关问题