inheritance
- Last UpdatedOct 07, 2026
- 4 minute read
The XRS scripting system supports single class inheritance, allowing a class to inherit members from a parent class.
Syntax
A class can inherit from another class using the colon ( : ) syntax:
class DerivedClass : BaseClass
{
// class members
}
Guidelines
These guidelines apply to inheritance.
-
Single inheritance only: A class can inherit from only one parent class. Multiple inheritance is not supported.
-
Inherited members: When a class inherits from a parent class, it automatically receives all methods and variables defined in the parent class.
-
Constructor inheritance: Parent class constructors are not automatically called. The parent constructor must be explicitly called inside the child constructor if needed.
-
Constructor limitations: Constructors do not support parameters. Only parameterless constructors are allowed.
-
Variable overriding: Overriding of class variables is not permitted. Child classes cannot redefine variables with the same name as parent class variables.
-
Method overriding: Overriding of class methods is permitted only when parent methods are marked as virtual.
-
Mark a method as virtual in the parent class to allow it to be overridden
-
Use the override keyword in the derived class to replace the parent's implementation
-
Attempting to override a non-virtual method will result in a compile error.
-
Access level: All inherited members are accessible in the derived class. There is no distinction between private and protected access modifiers for inheritance purposes.
Code example
The following example demonstrates basic inheritance, method overriding, and constructor behavior:
class Father
{
int a = 1;
int count = 0;
Father()
{
count = 1;
}
virtual void doSomething()
{
Runtime::Environment.Print("father");
}
}
class Child : Father
{
int b = 2;
Child()
{
count = 2;
}
override void doSomething()
{
Runtime::Environment.Print("Child");
}
}
class ChildNo : Father
{
int b = 4;
// No constructor defined - parent constructor is not automatically called
// doSomething() inherited without override - calls parent implementation
}
class Third : Child
{
int c = 5;
Third()
{
Father(); // Explicit call to parent constructor
}
}
Usage example
// Create instances
Father dad = new Father();
Child kid = new Child();
ChildNo simple = new ChildNo();
Third grandchild = new Third();
// Test inherited variables
Runtime::Environment.Print(dad.count); // Output: 1 (set in Father constructor)
Runtime::Environment.Print(kid.count); // Output: 2 (set in Child constructor)
Runtime::Environment.Print(kid.a); // Output: 1 (inherited from Father)
Runtime::Environment.Print(kid.b); // Output: 2 (Child's own variable)
Runtime::Environment.Print(simple.count); // Output: 0 (default value, no constructor called)
Runtime::Environment.Print(simple.a); // Output: 1 (inherited, default initialization)
// Test method overriding
dad.doSomething(); // Output: "father"
kid.doSomething(); // Output: "Child" (overridden)
simple.doSomething(); // Output: "father" (inherited, not overridden)
grandchild.doSomething(); // Output: "Child" (inherited from Child)
Constructor behavior
-
Explicit parent constructor call. Parent constructors must be explicitly called within the child constructor:
Third()
{
Father(); // Explicitly call parent constructor
}
-
No parameters supported. Constructors cannot have parameters** : **
// CORRECT
MyClass()
{
// constructor code
}
// ERROR - Parameters not supported
MyClass(int value, string name)
{
// This will cause a compile error
}
-
Default values only. Class variables are initialized to their declared default values or type defaults if no constructor is defined.
Variable inheritance rules
-
Variables cannot be overridden.
class Base
{
int value = 10;
}
class Derived : Base
{
int value = 20; // ERROR: Cannot override variable 'value'
int other = 30; // OK: New variable unique to Derived
}
Child classes can access parent variables but cannot redefine them. Each variable name must be unique within the inheritance hierarchy.
Method Override Rules
-
Only virtual methods can be overridden.
class Base
{
// Non-virtual method - cannot be overridden
void CannotOverride()
{
Runtime::Environment.Print("Base implementation");
}
// Virtual method - can be overridden
virtual void CanOverride()
{
Runtime::Environment.Print("Base implementation");
}
}
class Derived : Base
{
// ERROR XRS0000: Cannot override non-virtual method
override void CannotOverride()
{
Runtime::Environment.Print("Derived implementation");
}
// CORRECT: Overriding virtual method
override void CanOverride()
{
Runtime::Environment.Print("Derived implementation");
}
}
Error examples
-
Missing override keyword.
class Base
{
virtual void Process()
{
Runtime::Environment.Print("Base processing");
}
}
class Derived : Base
{
// ERROR XRS0000: Method must be tagged as override
void Process()
{
Runtime::Environment.Print("Derived processing");
}
}
2. Attempting to override non-virtual method
class Base
{
void Execute()
{
Runtime::Environment.Print("Base execution");
}
}
class Derived : Base
{
// ERROR XRS0000: Cannot override non-virtual method
override void Execute()
{
Runtime::Environment.Print("Derived execution");
}
}
3. Variable overriding (not allowed):
class Base
{
int counter = 0;
}
class Derived : Base
{
// ERROR: Cannot override variable
int counter = 10;
}
Integration with reflection
The Runtime::Reflection API automatically includes inherited methods when querying a class.
// Enumerate all methods for Third class (includes inherited methods)
list<string> methods = Runtime::Reflection->EnumerateMethodsForClass("Third");
// Returns methods from Father, Child, and Third classes
Best practices
-
Always mark overridable methods as virtual in the base class.
-
Use override keyword explicitly when replacing parent methods.
-
Call parent constructors explicitly when needed in derived class constructors.
-
Use unique variable names across the inheritance hierarchy.