Chapter 3 The Application Description Language
You can invoke a method defined in a parent class by a message to a derived class unless the method has been declared local in the parent class. The exceptions are the system messages Init and Destroy, the system default constructor message Construct, and any other method declared as a constructor by the developer. These methods are local to the class in which you declare them by default, and you may not invoke them by a message to a derived class. The rationale for this is that these messages are sent to objects and bases during initialization and destruction. If these messages could be inherited and were not redefined in each class, they might execute multiple times during the initialization or destruction of an object.
You can redefine or override methods in a derived class. If you want to access the version of a method defined in a base, you can direct the message using the self keyword qualified with the scope operator and the name of the base, provided the message executes in one of the methods of the derived class. There is currently no way to send a message to a base of an arbitrary object although there is a proposal to allow scope pairs with member self in member selection expressions Figure 3.45.
class A { on DoIt { ... } }; class B : A { on DoIt { ... 'DoIt => A::self; } }; B b; on Init { 'DoIt => b.A::self; // proposal; not implemented } |
Since a user-defined class can be a subclass of multiple classes, the ADL supports multiple inheritance. Multiple inheritance creates ambiguity when there are methods or members defined with the same name in two separate parent classes of the same subclass. Such ambiguous references in a method of a subclass are an error in C++, but the methods used to detect such conflicts are compute intensive and more appropriate for the compile-time type checking of C++ than the run-time lookup of the ADL.
AM2 searches superclasses in a depth-first manner during inheritance lookup. If this order is not appropriate, the author may use inherited declaration (unimplemented) to indicate in which subclass a method or member should be sought. The keyword inherited introduces such a declaration, followed by a base class name, the scoping operator, the type of the inherited member in the base, and the member name. After such a declaration, the member name refers to the similarly named member in the specified base, even if that member is not the first of that name in inheritance order. Figure 3.46 provides an example.
The choice of depth-first search is arbitrary but simple, and has the virtue that it establishes an unambiguous priority among parent classes. In the examples in Figure 3.46, Child is more closely related to Dad and GrandDad than it is to Mom.
The usage of the keyword derived in a scope pair with a member name or with the self keyword parallels the usage of the inherited keyword. The expression derived::self, when it appears in a method of a base of a derived object, refers not to the base but to the whole derived object. Likewise, derived:: prefixed to a member name refers to the member not (necessarily) in the base but rather the first occurrence of the member in inheritance order in the whole derived object. The rationale for the derived keyword is to provide part of the functionality of virtual functions in C++. You can divide this functionality in two parts:
Generated with Harlequin WebMaker