Questions on OOP in MQL5 - page 83

 

Yaah... How messed up people are with const(((.

To understand methods with const specifier

class CTest{
   int i;
public:
   CTest(int _i):i(_i){}
   int Get() const {return i;}
   int Get()   {return 2*i;}
};

void OnStart()
  {
   const CTest a(5);
   CTest b(8);
   Print(a.Get()); //5
   Print(b.Get()); //16
  }

Now do

   //int Get() const {return i;}

and then do vice versa:

//   int Get()   {return 2*i;}

)))

 
Alexandr Andreev:

Also a variant of the same code.


It's with the consts.

And you're sure that the input

Compare(CObject const *node,int const mode=0)

♪ you'll always feed ♪

CChartObjectRectangleX*

to write without checking?

return (  Time(1)-dynamic_cast<const ME*>(node).Time(1));

?

 
Alexandr Andreev:

the variant without the constitution since the base class has no reference to input parameters will also work correctly, although this style is not very clever

It will not work that way. You cannot change the signature in Compare. It's mainly needed for the QuickSort method, which is included in SB, to make regular sorting work.

If you change the signature, it's not an override of virtual function but overloading and it's calling method of base class CObject where return 0;

Of course, this can be solved by wrappers (decorating) to containers, but why these unnecessary movements, or else don't use SB and write everything from scratch.

 
Vladimir Simakov:

It seems to be the same as yours, only with fewer letters. So, it's a matter of taste, but I removed the extra variable (most likely, the compiler would have removed it as part of optimization).

Concerning my !node check. It must be replaced with CheckPointer(node)==POINTER_INVALID, but it is an overhead - a function call. Even if it's inlined, it's still at least dereferencing and checking the status flag. If only library or concrete, you've written program will use Compare methods, better !node and on code to watch for invalid pointer. If you too lazy to watch out for pointers or it's a library for underdogs, only CheckPointer(node)==POINTER_INVALID.

If you remove the const specifier you highlighted, you can't call these methods from a constant object.

UPD: the highlighted check can be removed, as it is in the called methods.

Vladimir, just in this case CheckPointer is redundant. dynamic_cast will return NULL for any failed cast, including if pointer is broken. Please correct me if I'm wrong. Tested long time ago, the test took 5 seconds).

Mechanism of CheckPointer working (in simple words, I'm not fluent in low-level terms) - it looks by pointer what kind of object, dynamic or static, if we can't get information, it means POINTER_INVALID. This may be the case if the dynamic object was removed, other situations I do not know, or uploaded rubbish to the pointer, but it must check the compiler, if you can not find loopholes.

and dynamic_cast does the same, also checking if the pointer can be cast to the required type, i.e. if it is a pointer of this type or a child class.

If the pointer is broken, dynamic_cast fails to detect anything and returns NULL.

That's why I have not used CheckPointer. But I usually use this check everywhere out of harm's way. After all, to find an error in software, which is not fallen down, a little easier it seems).

And what about non-const - in theory we can have a method like GetRatingByAnyFormula() { m_rating01=Formula01(); return m_rating01;}

would be quite inconvenient if it were not used in sorting right away, i.e. we would have to count the rating first and then call sorting by it. Or, as already said, write your own SB from scratch).

 
Aleksey Mavrin:

This is not good. The signature cannot be changed in Compare. It's mainly for the purpose of making QuickSort, the regular sorting method included in SB, work.

If you change signature, it's not overriding of virtual function, but overloading and method of base class CObject will be called, where return 0;

Of course, this can be solved by wrappers (decorating) to containers, but why these unnecessary movements, or don't use SB and write everything from scratch?

The most correct way is not to write on µl

 
Aleksey Mavrin:

Vladimir, in this case CheckPointer is redundant. dynamic_cast will return NULL for any unsuccessful cast, including if the pointer is broken. Please correct me if I'm wrong. Tested long time ago, the test took 5 seconds).

Mechanism of CheckPointer working (in simple words, I'm not fluent in low-level terms) - it looks by pointer what kind of object, dynamic or static, if we can't get information, it means POINTER_INVALID. This may be the case if the dynamic object was removed, other situations I do not know, or uploaded rubbish to the pointer, but it should check the compiler, if you can not find loopholes.

and dynamic_cast does the same, also checking if the pointer can be cast to the required type, i.e. if it is a pointer of this type or a child class.

If the pointer is broken, dynamic_cast fails to detect anything and returns NULL.

That's why I have not used CheckPointer. But I usually use this check everywhere out of harm's way. After all, to find an error in software, which is not fallen down, a little easier it seems).

And what about non-const - in theory we can have a method like GetRatingByAnyFormula() { m_rating01=Formula01(); return m_rating01;}

would be quite inconvenient if it were not used in sorting right away, i.e. we would have to count the rating first and then call sorting by it. Or you can write your own SB from scratch as already mentioned).

  1. The Compare-methods are defined as public, it means that any underdog, no matter how hard you try to explain it in specification, will shove there a nonvalid descriptor. Of course, if it's not a library, but just for yourself, you don't have to.
  2. I do not know how CheckPointer works, there up to . But in any case it's processor's clock and memory access (it could easily turn out to be virtual memory as well).
  3. About methods with the const specifier. If you write a library, you must always keep in mind that the object may need a constant, so in those methods, which do not change the state of the object, as it is desirable. Although, so far, for myself, I don't really bother with it.
  4. Writing your own system, this is probably the right decision. That's just interesting prospects in the pay / labor ratio is not visible yet, and therefore will not be finished, so for their own needs only).
 
Vladimir Simakov:

About my !node check. It should be replaced by CheckPointer(node)==POINTER_INVALID, but this is an overhead, function call.

The problem won't be in the overhead but in the fact that a broken pointer will change the program's logic. I.e. instead of detecting the problem, you will bury it even deeper.

CheckPointer should only be used for debugging purposes, or as an implementation of a weak pointer.

 
Vladimir Simakov:
  1. Compare-methods are defined as public, so any underdog, no matter how hard you tell him in specification, will shove an invalid descriptor there (let's call things by their proper names). Of course, if it's not a library, but just for yourself, you don't have to.
  2. I do not know how CheckPointer works, there up to . But in any case it's processor's clock and memory access (it could easily turn out to be virtual memory as well).
  3. About methods with the const specifier. If you write a library, you must always keep in mind that the object may need a constant, so in those methods, which do not change the state of the object, as it is desirable. So far, though, for myself, I don't really bother with it.
  4. Writing your own system, this is probably the right decision. That's just interesting prospects in the pay / labor ratio is not visible yet, and therefore there will not be anything finalized, so only for their own needs).

1. No argument, but what I was saying is that you do NOT need a CheckPointer (even for underdogs), because dynamic_cast may NOT return a non-invalid pointer, only NULL.

2. It's even interesting, but I cannot immediately think of an example which would allow to get a non-invalid pointer other than to kill the dynamic object or "dirty" memory directly while working on it.

I suppose there are still such ways, but they all most likely lie on the plane of bypassing compiler checks.

3,4 Agreed.

P.S.

I must have been wrong about the 1-st. The test says the opposite. It must be just an impression.)

void OnStart()
  {
      CChartObjectRectangle *base = new CChartObjectRectangle();
      CChartObjectRectangleX *rect = new CChartObjectRectangleX();
       CChartObjectRectangle * dbase  ;
      const CChartObjectRectangleX *drect  ;
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));
      dbase=dynamic_cast< CChartObjectRectangle *>  (base);
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL, " check? ",!dbase," broken? ", EnumToString( CheckPointer(dbase) ));
      delete base;
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));
      dbase=dynamic_cast< CChartObjectRectangle *>  (base);   
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));   
  }
 
Is it possible to declare a static array in the public class section and initialise it in the constructor? (as below) (or only element by element?)
 bool Mass[5] = { false, true, false, true, true };
 
Pavel Verveyko:
Can a static array be declared in the public class section and initialised in the constructor? (as below) (or only element-by-element?)

You can initialise a local array and perform an ArrayCopy to the appropriate array field:

class A{
public:
   bool Mass[5];
   A(){
       bool mass_init[5] = { false, true, false, true, true };
       ArrayCopy(Mass, mass_init);
   }
};
Reason: