AngelScript
Initialization of class members

The order in which the class members are initialized during the construction of an object becomes important when using inheritance, or when defining the initialization of the members directly in the declaration. If a member is accessed before it has been initialized the script may cause a null handle access exception, which will abort the execution of the script.

For a simple class, the order in which the members are initialized is the same as the order in which they were declared. When explicit initializations are given in the declaration of the members, these members will be initialized last.

  // The order of this class will be: a, c, b, d
  class Foo
  {
    string a;
    string b = a;
    string c;
    string d = b;
  }

When inheritance is used, the derived class' members without explicit initialization will be initialized before the base class' members, and the members with explicit initialization will be initialized after the base class' members.

  // The order of this class will be: a, b
  class Bar
  {
    string a;
    string b = a;
  }
  // The order of this class will be: d, a, b, c
  class Foo : Bar
  {
    string c = a;
    string d;
  }

This order of initialization has been chosen to avoid most problems with accessing members before they have been initialized.

All members are initialized immediately in the beginning of the defined constructor, so the rest of the code in the constructor can access members without worry. The exception is when the constructor explicitly initializes a base class by calling super(), in this case the members with explicit initialization will remain uninitialized until after the base class has been fully constructed.

  class Bar
  {
    Bar(string val) { a = val; }
    string a;
  }
  class Foo : Bar
  {
    Foo()
    {
      // b is already initialized here
      super(b); // a will be initialized in this call
      // c is initialized right after super() returns
    }
    string b;
    string c = a;
  }

Be wary about cases where a constructor or member initialization calls class methods. As class methods can be overridden by derived classes it is possible for a base class to unwittingly access a member of the derived class before it has been initialized.

  class Bar
  {
    Bar() 
    {
      DoSomething();
    }
    void DoSomething() {}
  }
  // This class will cause a null handle exception, because the Bar's constructor calls 
  // the DoSomething() method that accesses the member msg before it has been initialized. 
  class Foo : Bar
  {
    string msg = 'hello';
    void DoSomething() 
    { 
      print(msg); 
    }
  }