3

I have this problem:

// the classes
class cBase {};
class cDerived : public cBase {};

class cBaseArray
{
    // the array of pointers to cBase
    cBase** array;

    // overloaded operator that returns an element of the array
    cBase*& operator[](unsigned index)
    {
        // much more complicated, but simplified for example
        return array[index];
    }
};

class cDerivedArray : public cBaseArray
{
    // overloaded operator that returns a converted element of the array
    cDerived*& operator[](unsigned index)
    {
        // conversion required, but don't know how
        return static_cast<???>(cBaseArray::operator[](index));
    }
};

So how do I convert the reference to pointer to cBase returned by the operator[] of cBaseArray to refernce to pointer to cDerived that can be returned by the operator[] of cDerivedArray?

Rakib
  • 7,435
  • 7
  • 29
  • 45
  • You should [cast](http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used). – Csq Jun 09 '14 at 09:51
  • 1
    Well-formatted code on SO? Did that really happen? – polkovnikov.ph Jun 09 '14 at 09:51
  • Just a friendly note. Usually casting this way indicates some problems with the design of the application, also returning a reference to a pointer looks really weird and is asking for much [Fun](http://dwarffortresswiki.org/index.php/DF2012:Losing). It also takes much effort to keep track and ensure correctness of types. – luk32 Jun 09 '14 at 10:05
  • @luk32: I never return reference to pointers and I rarely use references in my code since I prefer the pointers, but the format of operator[] requires that so it can do both read/write. Maybe I should give up the comfort of "operator[]" and just use Set and Get for my classes which could be easily polymorphed... –  Jun 09 '14 at 10:27

2 Answers2

3

You have to dynamic_cast them.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
1

To return a reference, it must be a reference to a particular object. A cDerived*& must refer to an actual cDerived* (i.e. it must be an lvalue). Since you do not have any cDerived*, you cannot return a reference to one.

If you don't need to support the syntax myDerived[4] = anotherPtr; then you can just return cDerived *, which is no problem. If you must return a reference then you have no simple option other than to return cBase *&, and require the caller to do a dynamic_cast<> on the result if they want to access things that are not accessible through the cBase *.

It would be possible to design a special object that cDerived::operator[] returns and holds a reference to cBase *; and that object has operator= defined which can take a cDerived *, and that object has a conversion operator to cDerived *. This is added complication, I'd recommend not do to it unless you are really unhappy with the solution of my previous paragraph

NB. To get polymorphic behaviour you must have cBase be polymorphic, i.e. contain at least one virtual function - I'm assuming you intended this but left it out for brevity's sake.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • 1
    I gave up my answer, the design it's a bit contrived and would probably need a bigger re-structuring. These are good suggestions so +1, the OP will have to do some book-keeping by himself. – Marco A. Jun 09 '14 at 10:05
  • I see... I was hoping that the compiler can create a temporary cast object that can be returned, I was trying to avoid exactly what you said - forcing the caller to do the casting. I needed the fully functionality of the operator[] because it will access a complex dynamic array for both read and write while I was also trying to avoid the use of templates for different types supported by the array. –  Jun 09 '14 at 10:17
  • If the compiler did create a temporary object, then doing `myDerived[4] = anotherPtr;` would update the temporary object, not the internal array member – M.M Jun 09 '14 at 10:31
  • No, it would be correct, because it would return a reference to a temporary (cast) pointer that would only point to the array member I need to access, so myDerived[4] = anotherPtr would directly change the array, but maybe c++ standard does not allow for such operation. It's pity I can't control operator overloading as I require :( –  Jun 09 '14 at 10:43