Tip: To create new class, you can use menu File -> New -> New Class.
See also: QM classes tutorial
Most programming languages have classes. A class is a user-defined type that also has member functions. To understand classes, you have to be familiar with variables, user-defined types and user-defined functions.
In QM, class definition and other features are the same as of user-defined types. The only difference is that you use keyword class instead of type, and it only changes icon in popup lists from to .
To add a member function to a class, create new QM item of type 'Member function' (menu File -> New -> New Member Function). Its name must be like "ClassName.FunctionName". See also sub-functions.
To call a member function, use syntax var.FunctionName(), where var is a variable of that type. Example:
class Class a b c ;;define class Class Class var ;;create variable var of Class type var.Func(arguments) ;;call Class member function Func (QM item name is Class.Func) var.a=1; out var.a ;;access member variables
In a member function you can use keyword this to refer to the variable for which it is called. To access other member functions and variables of that class, in member functions you can use member name with or without "this." prefix. For example, to access member variable c, you can use this.c or c. To call other member function Func2, you can use Func2(arguments) or this.Func2(arguments).
You cannot use a class (as well as a simple type) if macro containing class definition is not compiled. To make a class always available, place it's definition (or #compile) into the init2 function or some other function that runs at startup. You can create/delete/rename member functions at any time.
You can add member functions to classes, other user-defined types and even to QM intrinsic types (str, int etc). Cannot add to arrays and interfaces.
See also: scope priority (when a member name matches a non-member name).
A class (only user-defined) can have three special functions - constructor, destructor and operator =. These functions cannot be called explicitly. They are recognized by QM item name.
|QM item name||Description|
|Constructor||Class||Is called implicitly when a variable of that class is created. Must not have parameters. Must not return a value.|
|Destructor||Class.||Is called implicitly before destroying a variable of that class (for example when a function containing a local variable of that class returns). Must not have parameters. Must not return a value.|
|Operator =||Class=||Is called implicitly when copying a variable of that class (var1=var2, Function(var), etc). Must begin with function ClassName&var, where var is another variable of that class. The function should properly copy var members (this.member=var.member...), because QM does not copy members if the class has an operator= function. Must not return a value.|
Here Class is class name. For example, if you want to add destructor to class Abc, create member function "Abc.".
Constructor and destructor of global variables are executed in QM main thread. Constructor is called when compiling the macro where the global variable is declared first time. Destructor is called before unloading QM file, for example when QM exits.
Elements of ARRAY cannot have constructor.
In these functions don't use end (except to generate warning) and avoid unhandled run-time errors. More info.
New classes can be derived from existing classes (extend them). This feature is called inheritance, because the derived class inherits member functions and variables of its base class (an existing class). Member functions of derived class can access non-private members (variables and functions) of base class. Members of derived class override members of base class with same name. A derived class is defined by adding colon (:) before the first member variable which is of base class type. Example:
class Base a b c class Derived :Base'x c d e Derived der der.a=5 ;;same as der.x.a=5 der.c=5 ;;c of Derived der.x.c=6 ;;c of Base
Members of base class can be accessed directly (e.g. der.a) or through the first member name (e.g. der.x.a). In member functions too: this.a or this.x.a or a or x.a.
QM 2.2.0. In derived class declaration can be used base type without member name. To access base members use the base type name. Bug. Example:
If in declaration used only base type, member functions of the derived class cannot declare variables of base type, because the base type name in code is interpreted as member name, not as type name. For backward compatibility, the bug cannot be fixed.
class Base a b c class Derived :Base c d e Derived der der.Base.c=6
Derived class, base classes and members can have constructors and destructors. When creating a variable of derived class, QM at first fills all memory with 0, then calls constructors for base classes, then for members (in the order as they are defined), then for derived class. Destructors are called in reverse order.
Public members (functions and variables) can be accessed from anywhere. Private members can be accessed only from member functions of that class. Protected members can be accesses only from member functions of that class and classes derived from that class.
By default, class members are public. To make a member function protected or private, use the Properties dialog or Ctrl+right-click it in the list of QM items. To make a member variable protected or private, place one or two hyphens before it in class definition. Example:
class Base a b class Derived :-Base'base --c d Derived der der.d=5 ;;OK: public member der.c=5 ;;error: private member der.b=5 ;;error: protected member
If member's name begins with __ (two _), or function is in private folder, it is not shown in the popup list of members, unless you are editing a member function or use Ctrl+Shift+. .
All sub-functions can access private/protected members of class of parent function, even if they aren't member functions.
QM 2.4.3. QM items named like Class_X can access private and protected members of that class.
Local variables of class type are allocated on the stack (like all local variables). To allocate a variable in dynamic memory, declare pointer and call function _new. It allocates memory and calls constructor. The _new function also can be used to allocate an array. When the variable is no longer needed, call function _delete. It calls destructor and frees memory. Example:
MyClass* c._new ... c._delete