Talking about the PLO in the lounge - page 5

 
Alexey Volchanskiy:

I've read everyone's different interests... I'm currently redesigning a class for virtual grid exposition and control, I need it.

And I've been struggling for 2 days with copy constructor and assignment operator. It's a complicated class with data members in the form of pointers...

 
Dennis Kirichenko:

I've been struggling for 2 days with copy constructor and assignment operator. There's a complex class with data members in the form of pointers...

I seem to write very primitive things...

 
Dennis Kirichenko:

You can use a pointer to a function.

Would it work that way with a virtual function?

And I've always disliked function pointers internally. I don't remember now why, when working in "pure C" - function pointers were used. But when I switched to C++ I had to give them up for some reason. And I haven't used them since that time. A pointer - it must be to an object.

But I'm not going to say that I'm "absolutely right". I agree that I have a lot of old-school old-school experience in me.

 
fxsaber:

I seem to write very primitive things...

Don't be modest.

I don't think anyone can match your virtuoso use of defines.

 
George Merts:


...With me this function looks like this:

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

      case FSM_BY_LAST_PRCDATA_A:      return(_CompareByLastPrcdataWith(pfdsAnother,true));
      case FSM_BY_LAST_PRCDATA_D:      return(_CompareByLastPrcdataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYDATA_A:      return(_CompareByLastMnydataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYDATA_D:      return(_CompareByLastMnydataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYLOTDATA_A:   return(_CompareByLastMnylotdataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYLOTDATA_D:   return(_CompareByLastMnylotdataWith(pfdsAnother,false));
      
      case FSM_BY_PRCYEARRECOVERY_A:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,true));
      case FSM_BY_PRCYEARRECOVERY_D:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYYEARRECOVERY_A:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYYEARRECOVERY_D:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYLOTYEARRECOVERY_A:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYLOTYEARRECOVERY_D:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,false));
      
      case FSM_BY_PRCVAR_A:            return(_CompareByPrcVarWith(pfdsAnother,true));
      case FSM_BY_PRCVAR_D:            return(_CompareByPrcVarWith(pfdsAnother,false));
      case FSM_BY_MNYVAR_A:            return(_CompareByMnyVarWith(pfdsAnother,true));
      case FSM_BY_MNYVAR_D:            return(_CompareByMnyVarWith(pfdsAnother,false));
      case FSM_BY_MNYLOTVAR_A:         return(_CompareByMnylotVarWith(pfdsAnother,true));
      case FSM_BY_MNYLOTVAR_D:         return(_CompareByMnylotVarWith(pfdsAnother,false));
      
      case FSM_BY_PRC_GRAILRATIO_A:    return(_CompareByPrcGrailratioWith(pfdsAnother,true));
      case FSM_BY_PRC_GRAILRATIO_D:    return(_CompareByPrcGrailratioWith(pfdsAnother,false));

      case FSM_BY_MAGIC_A:             return(_CompareByMagicWith(pfdsAnother,true));
      case FSM_BY_MAIGC_D:             return(_CompareByMagicWith(pfdsAnother,false));
      default:
         break;
      };
         
   return(NULL);
};

George, you can't see here whether _CompareByPrcVarWith() is a class method or an ordinary function, for example. In C++, there are pointers to class methods. They have their own specifics there. To be honest, I haven't tried to use such pointers in MQL5.

But I think that you still have a reserve for improving the code structure.

After all, what is a function?

FUNCTION(lat.functio, "execution, performance; duty") is a relationship between elements, in which a change in one entails a change in the other.

It is a function that does something. The same actions should be combined into the body of one function.

In your example it is obvious that the functions

_CompareByPartOfMaxDDWith(),

_CompareByPartOfMaxSLQueueWith(),

_CompareByLastPrcdataWith(),

_CompareByLastMnydataWith(), etc.

do a COMPARISE and give out the result of this comparison. They differ in names. Imho, it's not a good practice. They should distinguish themselves by parameters.

So. I think that we should either merge all the functions into one, or make them virtual methods, or template methods. Obviously, the classes must follow the "parent-son" hierarchy.

Generally speaking, it is very easy to write complex code and very difficult to write simple code.

 
Dennis Kirichenko:

George, you can't see here whether _CompareByPrcVarWith() is a class method or an ordinary function. In C++ there are pointers to class methods. They have their own specifics there. Honestly, I haven't tried to use such pointers in MQL5.

This (and all beginning with underscore) is a protected function of the class.

They are engaged in ARRANGEMENT and give out the result of this comparison. They differ in names. Imho, it's not a good practice. They'd better differ in parameters.

So. I think you should either merge all the functions into one, or make them as virtual methods, or template methods. Obviously, the classes must follow "parent-son" hierarchy.

Well, they are all merged into one!

There is only one function - Compare() but it has to perform a comparison with a passed key. Correspondingly, we choose one of the specific protector functions. That's why they are protected (protected), so that the user cannot access them - they are called only from Compare() and this is indicated by underlining.

This is also one of the code design rules - a function starting with an underscore is not intended to be called by users, it serves only certain in-class tasks. Access to it is restricted.

 
Dennis Kirichenko:

I've been struggling for 2 days with copy constructor and assignment operator. There is a complex class with data members in the form of pointers...


Denis, I wanted to say that everybody has different approaches. Actually, when I opened the thread yesterday, I was interested to see whether yesterday's whiners would appear, a la "a-a-a-a OOP is very complicated, SB is a horrible black box". They didn't show up, which is to be expected.

But people have emerged and each has a different approach. It's also interesting in terms of shared projects, which Renat talks so much about.

ZS: sharing in projects still doesn't work, tried it recently.

 
George Merts:

This (and all the ones starting with an underscore) are protec-tion functions of the class.

Well, they are merged into one!

There is only one function - Compare(), but it must perform a comparison against a passed key. Correspondingly, one of the particular protested functions is chosen. That's why they are protected (protected), so that the user cannot access them - they are called only from Compare(), which is indicated by underlining.

This is also one of the code design rules - a function starting with an underscore is not intended to be called by users, it serves only certain in-class tasks. Access to it is restricted.


How are they merged if you have many _CompareXXX() methods ? And there should be 1 as I understand it.

Question, for example, is the_CompareByPartOfMaxDDWith() method called anywhere else but in CFactoryBalanceResultSeries::Compare() ?

 
Dennis Kirichenko:

How do you merge if you have many _CompareXXX() methods ? And there should be 1 as I understand it.

Question, for example, is the_CompareByPartOfMaxDDWith() method called anywhere else but in CFactoryBalanceResultSeries::Compare() ?

If the _CompareXXX() method is alone, it is no different from the original Compare() virtual function.

The point is that the _CompareBy...() methods are called only from the main Compare(). And the underline at the beginning warns about it.

The Compare() general method accepts pointers to two objects and the key which specifies the comparison. In this general method the key is analyzed, and after that the specific method is called, which is designed to compare only one key. Moreover, each of these methods calculates the value of keys of two passed objects and depending on whether the key is int, double, bool or string - the method (also protected) of comparing of concrete type is called.

All methods _CompareBy...() - we could write in one function. But then, in my opinion, code readability would deteriorate.

 
George Merts:

If there is only one _CompareXXX() method, it is no different from the original Compare() virtual function.

The point is that the _CompareBy...() methods are called only from the main Compare(). And the underline at the beginning warns about it.

The Compare() general method accepts pointers to two objects and the key which specifies the comparison. In this general method the key is analyzed, and after that the specific method is called, which is designed to compare only one key. And each of these methods calculates the value of keys of two passed objects and depending on whether the key is int, double, bool or string - it is called the method (also protected) of comparison of concrete type.

All the _CompareBy...() methods could be written in one function. But then the code readability would deteriorate in my opinion.


I understand what you mean. I guess it's a matter of taste. But I would do everything in one method. Especially, if protected and private methods are not called anywhere else exceptCompare().