Recent

Author Topic: Constant of class can be changed?  (Read 2436 times)

d-_-b

  • New Member
  • *
  • Posts: 24
Constant of class can be changed?
« on: September 28, 2019, 11:55:16 pm »
So I'm going to assume I'm miss-using the const keyword in the class, but it feels wrong that I can change the const value at runtime, why? :-[

ideone code snippet with stdout.

Code: Pascal  [Select]
  1. program const_in_class;
  2. {$MODE objfpc}
  3. type
  4.   TKlazz = class
  5.   public
  6.     const
  7.       c: char = 'w';
  8.   end;
  9. begin
  10.         write(TKlazz.c);
  11.         TKlazz.c := 't';
  12.         write(TKlazz.c);
  13.         TKlazz.c := 'f';
  14.         write(TKlazz.c);
  15. end.
  16.  

 :'(
Code: Pascal  [Select]
  1. mov     ax,0013h
  2. int     10h
Denthor thanks for the vga programming tutorials | Download all tutorials

440bx

  • Hero Member
  • *****
  • Posts: 1193
Re: Constant of class can be changed?
« Reply #1 on: September 29, 2019, 12:20:12 am »
So I'm going to assume I'm miss-using the const keyword in the class, but it feels wrong that I can change the const value at runtime, why? :-[

ideone code snippet with stdout.

Code: Pascal  [Select]
  1. program const_in_class;
  2. {$MODE objfpc}
  3. type
  4.   TKlazz = class
  5.   public
  6.     const
  7.       c: char = 'w';
  8.   end;
  9. begin
  10.         write(TKlazz.c);
  11.         TKlazz.c := 't';
  12.         write(TKlazz.c);
  13.         TKlazz.c := 'f';
  14.         write(TKlazz.c);
  15. end.
  16.  

 :'(
using the keyword "const" the way it is used in the code you presented is a _writeable_ "constant" declaration.  What it really is, is a regular variable (allocated in the data segment - not on the stack), not a constant.

read what the reference manual says about "writeable constants".

HTH.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Zoran

  • Hero Member
  • *****
  • Posts: 1461
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Constant of class can be changed?
« Reply #2 on: September 29, 2019, 12:21:06 am »
It has nothing to do with classes.
If you read the manual (https://www.freepascal.org/docs-html/current/ref/refch2.html#x20-190002)
you will understand the difference between ordinary (true) constant and (unfortunately named) typed constant.

howardpc

  • Hero Member
  • *****
  • Posts: 3177
Re: Constant of class can be changed?
« Reply #3 on: September 29, 2019, 12:38:29 am »
Although const declarations within a class declaration do seem to be treated differently from global const declarations.
The directive {$WriteableConst off} raises a compiler error if you try to assign a new value to a global typed constant, but has no effect on assigning a new value to a typed const inside a class, which can freely be made.
Would this be a bug, or is it intended?

Thaddy

  • Hero Member
  • *****
  • Posts: 9157
Re: Constant of class can be changed?
« Reply #4 on: September 29, 2019, 04:43:07 am »
Would this be a bug, or is it intended?

I think that is a bug, because code like this should not work and throw a compile time error in J- state:
Code: Pascal  [Select]
  1. {$mode delphi}{$H+}{$J-}
  2. type
  3.   TTestme=class
  4.   const
  5.     c_one:integer = 1;
  6.     c_two:integer = 10;
  7.     c_three = 100;  // untyped works of course
  8.     c_four = 'W';   //
  9.   public
  10.     constructor create(a,b:integer);
  11.   end;
  12.  
  13.   constructor TTestme.create(a,b:integer);
  14.   begin
  15.     inherited create;
  16.     c_one := a;
  17.     c_two := b;
  18.   end;
  19. var
  20.   a:TTestme;  
  21.   b:TTestme;
  22. begin
  23.   a:=TTestme.Create(1000,10000);
  24.   a.free;
  25.   writeln(b.c_one,b.c_two);
  26. end.

Also demo's that they really work as class const : the values set in a, propagate to b.
I can see one reason why it can't work: {$J+/-} is a local switch, not a global switch.....
( I also tested with {$push}{$J-}....{$pop}, same effect: writable)

A way around it is to have the consts in a strict private section and access them through read-only properties.
Code: Pascal  [Select]
  1. type
  2.   TTestme=class
  3.   strict private
  4.   const
  5.     c_one:integer = 1;
  6.     c_two:integer = 10;
  7.   public
  8.   class property one:integer read c_one;
  9.   class property two:integer read c_two;
  10.   end;

But to my horror even strict private class const fields can be written to, even over unit boundaries!!
So apart from being always writable, the visibility specifier also has no meaning for class constants. (there is some logic to the latter, but not the former)
« Last Edit: September 29, 2019, 05:38:32 am by Thaddy »
also related to equus asinus.

Thaddy

  • Hero Member
  • *****
  • Posts: 9157
Re: Constant of class can be changed?
« Reply #5 on: September 29, 2019, 01:39:37 pm »
reported as issue 0036114 on Mantis.
also related to equus asinus.

Thaddy

  • Hero Member
  • *****
  • Posts: 9157
Re: Constant of class can be changed?
« Reply #6 on: October 04, 2019, 07:57:21 am »
reported as issue 0036114 on Mantis.

And fixed in trunk. (Tnx Sven)
« Last Edit: October 04, 2019, 07:59:06 am by Thaddy »
also related to equus asinus.