跳到主要内容

多文件完整示例

全 ST 工程使用统一符号表。类、派生类和使用这些类的程序可以拆分到不同的 .st 文件中,编译器会解析跨文件类引用和继承关系。

文件一:基类

counter.st
CLASS cCnt
VAR
CV : DINT;
END_VAR
VAR PUBLIC
Incr : DINT := 3;
END_VAR

METHOD PUBLIC Add : DINT
CV := CV + Incr;
Add := CV;
END_METHOD

METHOD PUBLIC AddTwice : DINT
AddTwice := THIS.Add();
AddTwice := THIS.Add();
END_METHOD

METHOD PUBLIC Drain : DINT
VAR_IN_OUT
Victim : cCnt;
END_VAR

Victim.CV := 0;
Drain := Victim.Add();
END_METHOD
END_CLASS

Drain() 位于 cCnt 类内部,因此可以访问另一个 cCnt 实例的私有成员 CV

文件二:派生类

double-counter.st
CLASS cDouble EXTENDS cCnt
METHOD PUBLIC OVERRIDE Add : DINT
Add := SUPER.Add() * 2;
END_METHOD
END_CLASS

文件三:程序

main.st
PROGRAM st111
VAR
d : ARRAY[0..1] OF cDouble;
test_array_dispatch : DINT;
END_VAR

test_array_dispatch := d[0].AddTwice() * 100 + d[1].Add();
END_PROGRAM

类数组中的两个元素是相互独立的实例:

  1. d[0].AddTwice() 两次动态调用 cDouble.Add(),结果为 12
  2. d[1].Add() 使用另一个实例的初始状态,结果为 6
  3. test_array_dispatch = 12 × 100 + 6 = 1206

该结果同时验证了成员默认初始化、数组实例隔离、THIS 动态匹配、OVERRIDE 重写和 SUPER 父类调用。

编译约束

以下情况会导致编译错误或警告:

场景结果
直接实例化抽象类编译错误。
非抽象派生类未实现全部抽象方法编译错误。
类直接或间接循环继承编译错误。
没有父类时使用 SUPER编译错误。
OVERRIDE 方法与父类方法签名不一致编译错误。
从类外部访问私有成员编译错误。
从无继承关系的代码访问保护成员编译错误。
将常量地址赋给类指针编译错误。
将临时实例地址保存到长生命周期指针悬空指针警告。