Matlab R2016a包名与类名相同时类构造报错求助
这确实是MATLAB R2016a里一个挺头疼的特定版本bug,刚好我之前也碰到过类似的命名冲突导致的构造函数调用异常问题。先给你把问题场景理清楚,再给几个不用修改大量硬编码名称的修复方案:
问题场景复现
目录结构
Rootdir └── +PkgClsName └── @PkgClsName └── PkgClsName.m
类代码(PkgClsName.m)
classdef PkgClsName < handle methods % 构造函数 function obj = PkgClsName() end % 深拷贝句柄对象 function new_obj = copy(obj) new_obj = PkgClsName.PkgClsName(); end end end
报错操作与信息
执行以下代码:
>> T = PkgClsName.PkgClsName; >> T.copy()
报错信息:
One or more output arguments not assigned during call to "_mcos_superclass_implicit_construct".
Error in PkgClsName.PkgClsName
Error in PkgClsName.PkgClsName/copy (line 11)
new_obj = PkgClsName.PkgClsName();
问题根源
R2016a对包名与类名完全相同的结构,在内部构造函数调用的解析逻辑上出了问题:当你在类方法里用PkgClsName.PkgClsName()这种完整路径调用构造函数时,它错误地触发了父类的隐式构造函数逻辑,而不是正确调用当前类的构造函数,导致输出参数未赋值的报错。这个bug在前后版本(R2010a、R2014a、R2017a)都被修复了,唯独R2016a存在这个问题。
无需修改命名的修复方案
方案一:用元类系统创建实例(最推荐)
修改copy方法,利用MATLAB的元类(metaclass)来创建新实例,完全绕过路径解析的bug。这种方法通用且稳定,适合批量修改:
function new_obj = copy(obj) % 获取当前对象的类元数据 cls = metaclass(obj); % 通过元类创建新实例(自动调用正确的构造函数) new_obj = cls.createInstance(); end
批量修改技巧
因为你有600多个同类结构的文件,可以写个简单的MATLAB脚本批量替换copy方法里的代码:
% 遍历所有目标类文件 rootDir = '你的Rootdir路径'; classFiles = dir(fullfile(rootDir, '+*', '@*', '*.m')); for i = 1:length(classFiles) filePath = fullfile(classFiles(i).folder, classFiles(i).name); % 读取文件内容 content = fileread(filePath); % 替换copy方法的内容 newContent = regexprep(content, ... 'function new_obj = copy\(obj\)\s*new_obj = (\w+)\.\1\(\);\s*end', ... 'function new_obj = copy(obj)\n cls = metaclass(obj);\n new_obj = cls.createInstance();\nend'); % 写入修改后的内容 fid = fopen(filePath, 'w'); fwrite(fid, newContent); fclose(fid); end
方案二:显式调用父类构造函数
修改构造函数,显式调用handle类的构造函数,可能会让R2016a的解析逻辑回归正常:
function obj = PkgClsName() % 显式调用handle父类的构造函数 obj = obj@handle(); end
这个方案不需要修改copy方法,但稳定性不如方案一,部分复杂类可能仍然会触发bug,适合简单类应急使用。
方案三:用eval间接调用构造函数
如果不想依赖元类,也可以用eval来间接调用构造函数,绕过路径解析问题:
function new_obj = copy(obj) % 获取当前类名 clsName = class(obj); % 通过eval调用构造函数 new_obj = eval([clsName '()']); end
不过eval在MATLAB里通常不推荐(可读性和性能稍差),但作为临时修复也是可行的。
内容的提问来源于stack exchange,提问作者Rody Oldenhuis

