How to dynamically cast the pointer of a derived object?

I would like to be able to add CObject derived objects to CArrayObj, but overload the [] operator to return the pointer of the derived object instead of CObject*

class MyArrayObj : public CArrayObj
{
public:
   CObject *operator[](const int index) const {return (CObject*)At(index);}
};

Similar to this but instead of returning the CObject pointer, I would first like to cast it to the derived object. So if I had…

class A : public CObject
{
public:
   void Print() { ::Print("I am A");}
};

class B : public CObject
{
public:
   void Print() { ::Print("I am B");}
};

… and I added them to the array…

A *a = new A;
B *b = new B;
   
MyArrayObj array;
   
array.Add(a);
array.Add(b);

…and I referenced the index…

for(int i=0;i<array.Total();i++)
      array[i].Print();

… it would dynamically cast the derived class to the [] operator. For example…

array[i].Print()
// would be the equivalent to 
((A*)array.At(i)).Print();
// if the object is A type OR
((B*)array.At(i)).Print();
//if the object is B type

…where the returned pointer is automatically resolved and casted to the objects original type.

I know I can use polymorphism to accomplish this, but I don’t want to rewrite the standard lib…

  1. Can’t be done. The return type of a function is fixed.
  2. Derive a base (interface) class (from CObject,) return that. All calls go through that. Let polymorphism (virtual) handle the rest.
  3. Why do you think you have to “rewrite the standard lib…”?

I’m currently making a new class whenever I need an object array.

class MyObjectArray : public CArrayObj
{
public:
   MyObject   *operator[](const int index)const {return (MyObject*)At(index);}
};

It would be nice to not have to do this every time.

That is potentially unsafe, unless you also override the add methods.
Don’t keep rewriting. Write a template once and done.

    template <T> class ObjectArray : public CArrayObj
    {
    public:
       T *operator[](const int index)const {return (T*)At(index);}
       void add(*T){ ... }
    };
    ////////////////////////
    ObjectArray<MyObject> a;
    a.add(new MyObject);
    MyObject* mo = a[0];     // No cast required.
    // a.add(new BadObject); // Won't compile unless Bad derived from My
  1. Why would I need to override Add if the class inherits from CObject?

BTW thanks for the template code… I tried it in the past but couldn’t implement it, now I realize that I wasn’t instantiating my objects correctly, duh.

Is there a more efficient method of the following implementation?

#include <Trade\SymbolInfo.mqh>
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template<typename T>
class CArrayTobj : public CArrayObj
{
public:
   T  *operator[](const int index) const { return (T*)At(index);}
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class MySymbol : public CSymbolInfo
{
public:
   MySymbol(const string symbol){ m_name=symbol;}
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
{
//---
   CArrayTobj<MySymbol>               *arrayOfSymbols;
   CArrayTobj<CArrayTobj<MySymbol>>    symbolGroups;
   
   //group 1
   arrayOfSymbols = new CArrayTobj<MySymbol>;
   arrayOfSymbols.Add(new MySymbol("EURUSD"));
   arrayOfSymbols.Add(new MySymbol("USDJPY"));
   arrayOfSymbols.Add(new MySymbol("EURJPY"));
   
   symbolGroups.Add(arrayOfSymbols);
   
   //group 2
   arrayOfSymbols = new CArrayTobj<MySymbol>;
   arrayOfSymbols.Add(new MySymbol("EURGBP"));
   arrayOfSymbols.Add(new MySymbol("USDCAD"));
   arrayOfSymbols.Add(new MySymbol("EURCAD"));
   
   symbolGroups.Add(arrayOfSymbols);
   
   for(int i=0;i<symbolGroups.Total();i++)
   {
      Print("Symbol Group ",i+1);
      for(int j=0;j<symbolGroups[i].Total();j++)
      {
         symbolGroups[i][j].RefreshRates();
         Print(symbolGroups[i][j].Name()," ",symbolGroups[i][j].Bid());
      }
   }  
}
//+------------------------------------------------------------------+

You derived MyObject from CObject . As long as you only put MyObject s (and classed derived from MyObject ,) in there no problem.

What happens if you try to put another class, BadObject (derived from CObject ,) in the array? (It works, they are both CObjects .) What happens at the retrieval cast? ( BadObject is not a MyObject .)

Ok… I see what you’re getting at now… I’m just going to keep it as is and use an abstract class to implement any and all polymorphic methods.

template <typename T> 
class MyArrayObj : public CArrayObj
{
public:
   T *operator[](const int index)const {return (T*)At(index);}
   //void add(*T){ ... }
};

class Abstract: public CObject
{
public:
   virtual void Print() = 0;
};
class A : public Abstract
{
public:
   void Print() { ::Print("I am A");}
};

class B : public Abstract
{
public:
   void Print() { ::Print("I am B");}
};

void OnStart()
  {
   
   A *a = new A;
   B *b = new B;
   
   MyArrayObj<Abstract> array;
   
   array.Add(a);
   array.Add(b);
   
   for(int i=0;i<array.Total();i++)
      array[i].Print();
   
  
}