Skip to content

Latest commit

 

History

History
84 lines (66 loc) · 2.54 KB

base-constructors.md

File metadata and controls

84 lines (66 loc) · 2.54 KB

Base constructors

Class constructors initialize the inheritance chain from the direct base class to the most-derived class. A derived constructor can pass arguments to its direct base constructor with a contextual base(...) call:

class ValueBase {
    public int32 value;

    public ValueBase(int32 initial) {
        value = initial;
    }
}

class AdjustedValue : ValueBase {
    public AdjustedValue(int32 initial) {
        base(initial + 1);
        value += 1;
    }
}

base(...) must be the first statement in a class constructor. It is consumed as constructor metadata rather than emitted as an ordinary function call. It is rejected in functions, struct constructors, classes without a base class, and later positions in a constructor body.

If a derived constructor does not contain an explicit base call, the compiler inserts base() before its body. This is valid only when the direct base constructor takes no arguments. A required-argument base constructor produces a semantic error until the derived constructor calls it explicitly with the correct argument count and types.

When a derived class declares no constructor, the compiler synthesizes a zero-argument constructor if any class in its base chain needs construction. This makes the automatic chain recursive:

class Root {
    public Root() {
        println("root");
    }
}

class Middle : Root {
}

class Leaf : Middle {
}

Constructing Leaf calls Root(), then the synthetic Middle() body, and finally the synthetic Leaf() body. Base-constructor failures use the normal exception propagation path, so the derived body does not run after a failure.

Constructor overloads

Classes and structs may declare multiple constructors with distinct parameter type lists (same rules as method overloads). Calls select the best applicable constructor; ambiguity and no-match are semantic errors (E_AMBIGUOUS_CONSTRUCTOR, E_NO_MATCHING_CONSTRUCTOR).

class Point {
    public int32 x;
    public int32 y;

    public Point() { x = 0; y = 0; }
    public Point(int32 v) { x = v; y = v; }
    public Point(int32 px, int32 py) { x = px; y = py; }
}

Point* a = new Point();
Point* b = new Point(3);
Point* c = new Point(1, 2);

base(...) in a derived constructor participates in the same overload resolution against the direct base class constructors. Implicit base() still requires a zero-argument (or synthetic) base constructor.

LLVM symbols are mangled with parameter types via the same CallableKey scheme as methods (Type.__ctor, Type.__ctor$int32, …).