2020版MATLAB更新了这一项,MATLAB Coder: Generate C++ classes from MATLAB classes,可把MATLAB中的类定义转到C++语言。
MATLAB面向对象并不是一个很多人都在用的功能,但对象的思想在MATLAB很多自定义函数中运用很广,运用面向对象的思想有助于提高代码的可拓展性和和我们的编程效率。
MATLAB面向对象在操作模式上,与C++非常相似,具有继承特性,支持子类、超类&父类,可以方便实现类指针。MATLAB帮助中的栏目Object-Oriented Programming
是一个很常用的好东西。
下面举一个例子,定义一个平面小车类。它具有时间、位置、速度、质量等属性(property);专门为类可以定义一些特有的函数,称为方法(method)、事件(event)等;这样可以把多个函数写到一个文件里,并且可以从外部调用。
classdef cart
%定义一个平面小车类
properties
t; % current time
r; % current Position, e.g. (x,y)
v; % current Velocity, e.g. (v_x,v_y)
T; % time series, e.g. N*1
R; % all the data from 0~t,e.g. N*2 & trajectory
V; % % all the data from 0~t,e.g. N*2
m; % mass
end
methods
function obj=cart(TrjMode)% Constructor
if nargin==0
TrjMode=0;
end
obj.t=0;obj.T=0;
switch TrjMode
case 1 % 指定好的一种初始状态
obj.r=[0,-2];obj.v=[1,0];
obj.R=[0,-2];obj.V=[1,0];
otherwise % 默认对象
obj.r=[0,0];obj.v=[0,0];
obj.R=[0,0];obj.V=[0,0];
end
end
function obj=RVUpdate(obj,tf,step)% 小车的位置更新规律
% 如直线运行、转弯等行为.
% 这里指定它的轨迹是在绕原点画大圆
t0=obj.t;
obj.T=linspace(t0,tf,step+1)';
rc=norm(obj.r);vc=norm(obj.v);w=vc/rc;
phase0=atan2(obj.r(2),obj.r(1));
obj.R=rc*[cos(w*obj.T+phase0),sin(w*obj.T+phase0)];
obj.V=vc*[-sin(w*obj.T+phase0),cos(w*obj.T+phase0)];
M=[cos(w*(tf-t0)), -sin(w*(tf-t0));
sin(w*(tf-t0)), cos(w*(tf-t0))];
obj.r=obj.r*M';obj.v=obj.v*M';
end
function drawTrajectory(obj)
figure(1),
plot(obj.R(1,1),obj.R(1,2),'bo');hold on;
plot(obj.R(:,1),obj.R(:,2));
plot(obj.r(1),obj.r(2),'ro');
xlabel('x');ylabel('y');axis equal
legend('initial R','trajectory','end R');hold off;
end
end
end
创建类对象的一个实例c,并依次使用对象c的两个函数,可以在命令行输入
c=cart(1); % 等式右边是构造器函数,可以在这里指定参数
c=c.RVUpdate(3,300);
c.drawTrajectory
绘图得到
如果要创建对象数组,比如100辆小车c2,可以这样
c2(100)=cart;
等式右边的构造器函数没有输入参数TrjMode,所有出来的都是默认对象,
>>c2(1)
ans =
cart (具有属性):
t: 0
r: [0 0]
v: [0 0]
T: 0
R: [0 0]
V: [0 0]
m: []
这样做需要从头到尾给它赋值,当然你可以在构造器里直接赋值
for i=1:100
c2(i).r=randn(1,2); c2(i).v=0.1*randn(1,2);
c2(i).R=c2(i).r; c2(i).V=c2(i).v;
end
可以看到,除了才method以后的内容,前面的定义相比于每次单独创建结构体struct要方便得多:
c=struct('t',time,'r',Position,'v',Velocity,...
'T',Time,'R',PositionMat,'V',VelocityMat);
我们注意到,对对象c的方法c=c.RVUpdate(3,300)
的调用,函数返回值赋值到左边,才能起到对c改动的作用。这样每次调用方法函数时,都要在等号左边写上它自己,非常麻烦。
这篇文章li12242 - Matlab指针指出,基于handel超类,可以实现指针类。
handle类型对象在赋值给其他变量时,不会对原始对象进行复制。此外,在函数中对handle类型对象做修改后,也不需在将其作为返回参数输出。也就是说,在使用handle类型对象时,我们可以认为所操作的就是一个指针,其指向的内容就是构造函数初始化的实例。
所以,只需要把定义文件第一行改动一下
classdef cart < handel
%定义一个平面小车类
properties
t; % current time
r; % current Position, e.g. (x,y)
……
……
……
end
end
这样,就可以直接调用对象函数了
c=cart(1);
c.RVUpdate(3,300);
c.drawTrajectory
超类Handle Class称作句柄类,类似于C++中的类指针。它的特性是Mathworks-handle 类:
-
handle 类是遵守句柄语义的所有类的超类。句柄是引用 handle 类的对象的变量。多个变量可以引用同一个对象。
-
handle 类是抽象类,这样您无法直接创建该类的实例。使用 handle 类派生其他类,可以是其实例为句柄对象的具体类。
使用classdef定义的handle类的子类,我在这里叫做类指针,相对于类对象,他两的区别可以看这篇文章,CSDN-哈哈kls -类对象与类指针。
使用它的优点是在进行复杂对象的参数传递时,避免了将整个对象复制一遍作为实例传递进去——而是只传递一个指针进去,直接在原来的对象上进行操作,从而大大节省了时间。比如做两个小车的碰撞判断等
for i=1:100
flags(i)=-c1.collide(c2(i));
end