我们做事是不是应该认真一点?
作者:admin 日期:2008-04-06
一个奇怪的"发现二义性的名称"问题(VB6.0)
作者:admin 日期:2008-04-04
今天QQ上一好友发来个问题,说是工程"发现二义性的名称".
我想,这个好解决啊,不就是重名么.叫他搜索一下,未果,说只有那一处.
按理说不可能的.于是就传了工程过来瞧瞧.
一编译,还真是这样,说是"发现二义性的名称",但是,我在整个工程范围都搜索过了,绝对没有同名的函数与过程...
哎,这还真有意思了!
难道是VB6的一个BUG?? (测试工程见文后A工程)
这可真要弄清楚!
工程是一个ActiveX DLL,添加了十三个类模块.
出现提示的那些函数分别处于三个类模块中,于是就把其它类模块都移除出工程,开始研究.
发现只要把这三个类设置为私有,就不会有此问题;(此时需要有一个公有类,ActiveX DLL必须至少要有一个)
但到底是什么原因呢?
找来找去,的确没有重复的名称!
真晕了,我真的遇到一个BUG了?
接下来怎么办?
我就不断地编译,只要有提示哪个过程有二义性,我就注释它;
如此反复,直到每个类模块只有一个公有过程时,编译通过了.
有意思.
然后再将所有注释还原,编译,咦~~~通过了?!
真怪!!
想了想,问题应该是出在类模块文件里面.
用UE打开,再把原有问题的一个类也打开,使用UE的文本比较,一下子就发现了问题所在.看下面是两段过程的源代码:
可见,说二义性名称的类模块里面,多了"Attribute TestFunction2.VB_UserMemId = 32767"一行.
看名字,应该是过程属性,于是就到IDE里看了一下,的确,工具---过程属性---高级里面可以设置.
但这不可能会有两个过程有同样属性的.
于是问QQ上,编写此代码时做了些什么操作?
他想了想,说用到了一个名为"Smart indent"的插件,把代码整理了一下而已,其它都只是复制粘贴,自己没操作过工具菜单里的东西.
原来是这样.
看来这插件可能有误伤,搞得函数的属性值在文件源码级相同了.
为了验证,就需要重现此问题.
便写了两个测试工程,在这里下载:
点击下载此文件
工程A是无法通过编译的,问题如上所说.
工程B正常,用于对比.
至此,问题根源算是搞清楚了.
不过这VB6IDE也太不负责了.属性冲突就说出来呗.干嘛要说二义性名称!!
记得以前测试API方式调用一个DLL,由于DLL内部错误,造成载入失败,VB6IDE也报个"未找到文件",晕!!
看来以后要小心了,VB6IDE报的错误也许并不是像它的意思那样.
要是遇到这种莫名其妙的,无法在代码里找到的错误,那可能就要好好考虑一下了.
我想,这个好解决啊,不就是重名么.叫他搜索一下,未果,说只有那一处.
按理说不可能的.于是就传了工程过来瞧瞧.
一编译,还真是这样,说是"发现二义性的名称",但是,我在整个工程范围都搜索过了,绝对没有同名的函数与过程...
哎,这还真有意思了!

难道是VB6的一个BUG?? (测试工程见文后A工程)
这可真要弄清楚!
工程是一个ActiveX DLL,添加了十三个类模块.
出现提示的那些函数分别处于三个类模块中,于是就把其它类模块都移除出工程,开始研究.
发现只要把这三个类设置为私有,就不会有此问题;(此时需要有一个公有类,ActiveX DLL必须至少要有一个)
但到底是什么原因呢?
找来找去,的确没有重复的名称!
真晕了,我真的遇到一个BUG了?

接下来怎么办?
我就不断地编译,只要有提示哪个过程有二义性,我就注释它;
如此反复,直到每个类模块只有一个公有过程时,编译通过了.
有意思.
然后再将所有注释还原,编译,咦~~~通过了?!

真怪!!
想了想,问题应该是出在类模块文件里面.
用UE打开,再把原有问题的一个类也打开,使用UE的文本比较,一下子就发现了问题所在.看下面是两段过程的源代码:
复制内容到剪贴板
程序代码

'不正常的类
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "cTestA"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit
Public Function TestFunction1() As Long
Attribute TestFunction1.VB_UserMemId = 32767
TestFunction1 = 1
End Function
Public Function TestFunction2() As Long
Attribute TestFunction2.VB_UserMemId = 32767
TestFunction2 = 1
End Function
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "cTestA"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit
Public Function TestFunction1() As Long
Attribute TestFunction1.VB_UserMemId = 32767
TestFunction1 = 1
End Function
Public Function TestFunction2() As Long
Attribute TestFunction2.VB_UserMemId = 32767
TestFunction2 = 1
End Function
复制内容到剪贴板
程序代码

'正常的类
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "cTestB"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit
Public Function TestFunction1() As Long
TestFunction1 = 1
End Function
Public Function TestFunction2() As Long
TestFunction2 = 1
End Function
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "cTestB"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit
Public Function TestFunction1() As Long
TestFunction1 = 1
End Function
Public Function TestFunction2() As Long
TestFunction2 = 1
End Function
可见,说二义性名称的类模块里面,多了"Attribute TestFunction2.VB_UserMemId = 32767"一行.
看名字,应该是过程属性,于是就到IDE里看了一下,的确,工具---过程属性---高级里面可以设置.
但这不可能会有两个过程有同样属性的.
于是问QQ上,编写此代码时做了些什么操作?
他想了想,说用到了一个名为"Smart indent"的插件,把代码整理了一下而已,其它都只是复制粘贴,自己没操作过工具菜单里的东西.
原来是这样.
看来这插件可能有误伤,搞得函数的属性值在文件源码级相同了.
为了验证,就需要重现此问题.
便写了两个测试工程,在这里下载:

工程A是无法通过编译的,问题如上所说.
工程B正常,用于对比.
至此,问题根源算是搞清楚了.
不过这VB6IDE也太不负责了.属性冲突就说出来呗.干嘛要说二义性名称!!
记得以前测试API方式调用一个DLL,由于DLL内部错误,造成载入失败,VB6IDE也报个"未找到文件",晕!!
看来以后要小心了,VB6IDE报的错误也许并不是像它的意思那样.
要是遇到这种莫名其妙的,无法在代码里找到的错误,那可能就要好好考虑一下了.
