четверг, 5 февраля 2015 г.

Briefly. About “reverse stability”

Original in russian: http://programmingmindstream.blogspot.ru/2014/08/blog-post_17.html

I’ll go back a long way, to C++ where there’s no operator with (and luckily never will be).

But there are “block variables” and the constructions like int & X = MyClass.MyField.MySubField;).
Let the code be like:

class A
{
 private:
  int X; // - this is a private member of A class
};//A
 
int X = 0; // - это глобальная переменная
 
class B : A
{
 void Dummy ()
 {
  X = 123; // - here the compiler will grumble that “there is a private member 
           //   which can “shade” the global variable” 

 };
};//B

As a result, the code will not be compiled.

How can it be compiled?

What if we try this one:

class A
{
 private:
  int X; // - this is a private member of A class
};//A
 
int X = 0; // - This is Global variable
 
class B : A
{
 void Dummy ()
 {
  ::X = 123; // - here the compiler will not grumble because will “understands” 
             // that X is a GLOBAL variable and ONLY X is
 };
};//B

This strategy of the compiler is the RIGHT one.

If code could be compiled, what would we get?

We’d get this:

class A
{
 protected:
  int X; // - this is a “protected” member of A class
};//A
 
int X = 0; // - this is a global variable
 
class B : A
{
 void Dummy ()
 {
  X = 123; // - WHY! Here X “suddenly” becomes a member of A class 
           // and not a global variable
 };
};//B

And so we get an “unexpected result”.

But! The compiler does not do so.

That is what we call a “reverse stability”.

And the operator with in Delphi does not have the “reverse stability”. It’s a pity.

Let me explain:
type
 TA = class
  public
   Caption : String;
 end;//TA
 
 TB = class
  public
   Caption : String;
   A : TA;
 end;//TB
...
procedure TB.SomeProc;
begin
 with A do
  Caption := '123'; // - This is assigned to Self.A.Caption 
end;

And in this way:
Unit uA;
...
type
 TA = class
  private
   Caption : String;
 end;//TA
...
Unit uB;
...
 TB = class
  public
   Caption : String;
   A : TA;
 end;//TB
...
procedure TB.SomeProc;
begin
 with A do
  Caption := '123'; // - This is assigned to Self.A.Caption 
end;

We’ll say: WOW!

One more thing…

How could we write in C++?
void TB::SomeProc ()
{
 ...
 {
  ...
  std::string & vCap = A.Caption;
  vCap = '123';
  ...
 }
 ...
}

Do you understand why I wrote about the “block variables” and about &? Do you understand why “in this context” C++ does not need operator with.

Комментариев нет:

Отправить комментарий