前言
2023.3.12 植树节
2023.3.15 更新
今天看到一个文章讲父类句柄和子类句柄的问题的
父类句柄可以指向子类对象(只可以访问部分内容)和父类对象
子类句柄只可以指向子类对象,不可以指向父类对象
父类句柄 = 子类句柄; 子类句柄可以直接赋值给父类句柄,不需要转换
$cast(子类句柄,父类句柄); 父类句柄给子类句柄需要转换,还有可能转换失败
结果:子类句柄指向父类句柄所指向的对象。此时若父类句柄指向的是子类类型的对象则结果就是子类句柄指向子类对象,仿真不会报错,但如果父类指向的是父类对象则结果就是子类句柄指向了父类对象,这是仿真不允许的,会报错。
转换的时候就是看父类句柄指向的对象类型是否是子类,是就输出1,转换成功,是父类对象的话,输出为0,转换失败
一、父类句柄h1、子类句柄h2
h1=h2
:合法,但是在调用相同对象的成员时,有不同的表现。
赋值后父类还是只能调用父类的成员,子类可以使用super
找到父类中的变量,但是父类不能够引用子类中的同名变量
举例说明
1、首先,创建了一个父类对象,然后让子类指针去指向父类对象,这是错误的。bad是空句柄,没有创建对象。父类句柄指向的父类对象,没办法转换;若父类指向的是子类对象,可以转换
。如果使用cast强制转换的话,编译不会报错,但是转换会失败。
再者,子类bad指向了一个父类对象,bad_crc是在子类中的,所以也没办法调用。
Transaction tr; //声明句柄
BadTr bad;
tr = new(); //创建父类对象
bad = tr;
$display(bad.bad_crc);
2、下面是创建子类对象,让父类句柄指向子类对象,这样是可以的
bad = new(); //创建子类对象
tr = bad; //父类句柄指向子类对象
if(!$cast(bad2,tr)) //动态类型转换,检查tr的源对象是否是bad2类型或者其子类
$display("failed");
$display(bad2.bad_crc);
bad2.display(); //这里调用的是子类的函数
二、virtual虚函数
建议除了new()函数
之外不能定义为虚方法,其余方法都定义为虚方法。添加了没有坏处(父类里面的所有成员变量和方法子类都会继承)
静态绑定
:static binding,不同句柄调用的内容不一样
动态绑定
:dynamic binding,利用虚方法virtual
声明函数,称之为虚方法(并没有“虚变量”)。不需要担心句柄指向的对象类型是父类还是子类,它可以进行动态动态方法查找dynamic method lookup
- 只需要在父类里面声明一次,尽量在最底层中继承
- 虚方法的继承:方法task/function的继承必须遵循相同的参数和返回类型(完全相同),否则,子类定义的方法会归为同名不同参的其他方法
new
不可以用virtual修饰,没有返回值,可以有参数- 如果没有定义为virtual的话,就会去调用父类的函数
- 解决了父类句柄指向子类句柄中的同名方法的动态查找问题,解决不了父类句柄查找子类对象里面变量的问题,无论父类句柄指向的是父类/子类对象,都无法找到子类对象中的成员变量,唯一办法将父类句柄转换为子类句柄。(只有虚方法没有虚变量)
- 如果函数同名,但参数类型或者个数不同,叫函数重载