You apply a hard type to a variable. When you do this, you tell the compiler that you know what you are doing, and the compiler trusts you.
(1) What is Member2's address? Is this a possible "access violation"?
When you assign a value to a class member, the class definition of the variable is used by the compiler to calculate the offset of this member in memory space, so if you have a class declaration as follows:
type TMyClass = class(TObject) Member1: Integer; //4 bytes Member2: Integer; //4 bytes end;
the representation in memory of this object is as follows:
reference (Pointer) to the object | | --------> [VMT][Member1][Member 2][Monitor] Offset 0 4 8 12
When you issue a statement like this:
MyObject.Member2 := 20;
The compiler simply uses this information to calculate the memory address for applying this purpose. In this case, the assignment compiler can be translated into
PInteger(NativeUInt(MyObject) + 8)^ := 20;
So, your assignment is successfully executed only because the memory manager is working (by default). When you try to access a memory address that is not part of your program, AV is created by the operating system. In this case, your program takes up more memory from the OS than is required. IMHO, when you do not receive AV, you are, in fact, out of luck, because your program memory can now be silently damaged. Any other variable located at this address can change its value (or metadata), and this will lead to undefined behavior.
(2) ToString () method points to the same address
Since the ToString () method is virtual, the address of this method is stored in VMT, and the call is determined at runtime. Take a look at What data is contained in TObject? and read the reference book section: Delphi Object Model .
(3) why do a and b have the same ClassName?
The class name is also part of the runtime metadata of the object. The fact that you apply an irregular shape to an object does not change the object itself.
(4) a and b are two different variables
Of course you declared it, look at your code:
var a: TClassA; b: TClassB;
Well, two different variables. In Delphi, object variables are links, so after some lines of code refer to the same address, but that's another thing.
(5) if b is TClassA, why use the "MyToString" method?
Because you tell the compiler that you are OK, and as said, the compiler trusts you. These are hacks, but Delphi is also a low-level language, and you are allowed to do a lot of crazy things if you want, but:
Play in safe mode
If you want (and you probably want most of the time) to be safe, do not use a hard trick like this in your code. Use as an operator :
The operator how performs the tested types of techniques. Expression
object as a class
returns a reference to the same object as the object, but with the type specified by the class. At run time, the object must be an instance of a class, denoted by a class or one of its descendants, or be nil; otherwise, an exception is thrown. If the declared type of the object is not associated with the class, that is, if the types are different, and one is not the ancestor of the other, a compilation error occurs.
So, with the as operator, you are safe, both at compile time and at runtime.
Change your code to:
procedure ShowInstance(A: TClassA); var b: TClassB; begin b := A as TClassB;