Type() method of CObject derivatives in Standard library, always return 0 when casting to CObject. - page 3

 
Mohammad Hossein Sadeghi:

...

Suppose that I have a subclass of CCheckGroup as UiCheckGroup, it has a private member CCheckBox, I have no way to find out the type of controls in the UiCheckGroup.

So I believe the work around would be defining a virtual Type() method for each control type in a future update of standard library.

Update: I have no way to find out the type of controls in the UiCheckGroup, other than cloning the CCheckGroup or dynamic_cast, or ...

 

CCheckGroup only has check-boxes. Why would you need to iterate them to get an ID when they can only ever be check-boxes?

 
Mohammad Hossein Sadeghi:

Update: I have no way to find out the type of controls in the UiCheckGroup, other than cloning the CCheckGroup or dynamic_cast, or ...

Dynamic cast should be the best way, it should not have any influence on performance since the pointer is the only thing that is allocated, maybe some update of virtual methods table. Not significant at all. 
 
Amir Yacoby:
Dynamic cast should be the best way, it should not have any influence on performance since the pointer is the only thing that is allocated, maybe some update of virtual methods table. Not significant at all. 
Maybe but iterating all types until you find the good one is really not a nice way to code in my opinion. Having some king of Type is a must.
 
I am an advocat of referring the standard library as a starting point. Its not recieved from mount Sinai, its not holy. It will make life much easier, and also to solve this specific problem. 

Just out of curiosity, what is the need to iterate the controls on the panel in order to find one specific control? 

* the first part I meant that imo prople who have better ideas, shouldnt  hesitate to change the std lib

** in the second part i meant that usually polymorphism does not need to know the type of object in a base container
 
Alain Verleyen:
Maybe but iterating all types until you find the good one is really not a nice way to code in my opinion. Having some king of Type is a must.

I don't really see a difference. To prove it here is a benchmark, tested on MT4. 

#include <Arrays\ArrayObj.mqh>

class Foo : public CObject{public:virtual int Type()const{return 1;}};
class Bar : public Foo    {public:virtual int Type()const{return 2;}};

void OnStart()
{
   
   int TEST_ITERS = 100000;
   CArrayObj arr;
   arr.Add(new Foo);
   arr.Add(new Foo);
   arr.Add(new Foo);
   arr.Add(new Foo);
   arr.Add(new Bar);
   arr.Add(new Foo);
   int total = arr.Total();
   string res_template = "iterations(%d), sanity-check(%s): Method=%s, time=%d";
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+   
   ulong ms = GetTickCount();
   ulong count = 0;
   for(int i=0; i<TEST_ITERS; i++)
      for(int j=0; j<total; j++)
         if(arr.At(j).Type() == 2)
            count++;
    
   printf(res_template, 
      TEST_ITERS, string(count == TEST_ITERS),
      "obj.Type()", GetTickCount() - ms
   );
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+      
   ms = GetTickCount();
   count = 0;
   for(int i=0; i<TEST_ITERS; i++)
      for(int j=0; j<total; j++)
         if(CheckPointer(dynamic_cast<Bar*>(arr.At(j))))
            count++;
     
   printf(res_template, 
      TEST_ITERS, string(count == TEST_ITERS),
      "dynamic_cast<>", GetTickCount() - ms
   );
}

Results:

//FOO EURUSD,Weekly: iterations(1000000), sanity-check(true): Method=obj.Type(), time=140
//FOO EURUSD,Weekly: iterations(1000000), sanity-check(true): Method=dynamic_cast<>, time=219


In terms of perceptible GUI performance there is no difference. 

 
Amir Yacoby:
I am an advocat of referring the standard library as a starting point. Its not recieved from mount Sinai, its not holy. It will make life much easier, and also to solve this specific problem. 

Just out of curiosity, what is the need to iterate the controls on the panel in order to find one specific control? 

* the first part I meant that imo prople who have better ideas, shouldnt  hesitate to change the std lib

** in the second part i meant that usually polymorphism does not need to know the type of object in a base container

I agree, however, I have been burned in the past by modifying the standard lib because the updater will replace the files with new updated files and all your changes are lost. If you clone the STL into a different directory then you miss the bug fixes that come with updates. It's always best to subclass whenever possible, and there hasn't been a single example ITT of where subclassing wasn't the solution. 

 
nicholi shen:

I agree, however, I have been burned in the past by modifying the standard lib because the updater will replace the files with new updated files and all your changes are lost. If you clone the STL into a different directory then you miss the bug fixes that come with updates. It's always best to subclass whenever possible, and there hasn't been a single example ITT of where subclassing wasn't the solution. 

Cloning of course.
As for bug fixes and stuff like this, the waiting does not worth holding you back.
And also you will not need their fixes if you already changed the version to something better.
And also you can watch for updates and change logs.

Some classes that are just wrappers, like positioninfo, can be kept and subclassed for easy copy from time to time.
 
nicholi shen:

I don't really see a difference. To prove it here is a benchmark, tested on MT4. 

Results:


In terms of perceptible GUI performance there is no difference. 

Your test is not correct. On the approach without type, you need to check all (applicable) derived classes, you have only 1, attached an example with 13 which is not much for a real GUI :

2018.10.16 11:53:39.738    283776 EURUSD,M5: iterations(100000), sanity-check(false): Method=dynamic_cast<>, time=1390
2018.10.16 11:53:38.350    283776 EURUSD,M5: iterations(100000), sanity-check(false): Method=obj.Type(), time=610

Anyway if this method is good for you, no problem. I am just saying there are several approaches and each one is free to choose the one he prefers. Often what is best solution for one is worst solution for someone else.

There are 3 solutions proposed in the thread, people have just to pick one that matches their needs and preferences.

Files:
283776.mq4  5 kb
 
Alain Verleyen:

Your test is not correct. On the approach without type, you need to check all (applicable) derived classes, you have only 1, attached an example with 13 which is not much in a real GUI :

2018.10.16 11:53:39.738    283776 EURUSD,M5: iterations(100000), sanity-check(false): Method=dynamic_cast<>, time=1390
2018.10.16 11:53:38.350    283776 EURUSD,M5: iterations(100000), sanity-check(false): Method=obj.Type(), time=610

Anyway if this method is good for you, no problem. I am just saying there are several approaches and each one is free to choose the one he prefers. Often what is best solution for one is worst solution for someone else.

There are 3 solutions proposed in the thread, people have just to pick one that matches their needs and preferences.

Doesn't change a thing. Anything below 2ms is completely imperceptible to the human brain, and the difference between the two methods works out to mere microseconds on a full blown GUI. In this case it all comes down to developer preference. For the record, my preference is to use obj.Type() but in a pinch dynamic-casting will do, and there won't be any negative consequences for doing so. 

Reason: