-1
class Element { };
class Container {
    vector<Element*> elements;
};

The above is the original code. I was told not to change the above code. Now I have

class IndexElement: public Element {
    int b_index;
};

class Container* ctr;

Now I have ctr->elements. But Element has no member b_index. Any simple method to redirect the attribution of elements from Element to IndexElement? Thanks in advance!

SergeyA
  • 61,605
  • 5
  • 78
  • 137
Taitai
  • 584
  • 2
  • 7
  • 18

2 Answers2

0

You have one option: you know that you have a IndexElement and not a Element in the vector, and then you can use static_cast<IndexElement*>(elements[i]);. Be aware that if you don't have only IndexElement, then this will utterly break.

If you can modify b, then you have another option, by making b virtual. If you don't know, you may have Elements and IndexElements, and in that case use dynamic_cast<IndexElement*>(elements[i]); and test it the result is nullptr or not. In this instance, b must be virtual (hence virtual destructor).

(I assume we are in Container, so direct access its members)

Full trial (that will break because no allocated elements) with the modified Elements:

#include <vector>

using namespace std;

class Element{
public:
    virtual ~Element() {}
};

class Container{
    public:
vector<Elements*>elements;
};

class IndexElement: public Element{
int index;
};

int main()
{
    Container aa;
    static_cast<IndexElement*>(aa.elements[0]);
    dynamic_cast<IndexElement*>(aa.elements[0]);
    return 0;
}
Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
0

Well, even without virtual and RTTI (dynamic cast) you still have the option to track and check the IndexElement instances created, for example:

std::unordered_set<Element *> idxElemSet;

class IndexElement: public Element {
    int b_index;
public:
    IndexElement(int index) : b_index(index)
    { idxElemSet.insert(this); }

    IndexElement(const IndexElement& other) : b_index(other.b_index)
    { idxElemSet.insert(this); }

    // might also need the move constructor in case of c++11

    ~IndexElement()
    { idxElemSet.erase(this); }

};

int main()
{
    Container c;
    ...
    Element* e = c.elements[0];

    if (idxElemSet.find(e) != idxElemSet.end()) {
        IndexElement* ie = static_cast<IndexElement*>(e);
        // do something with ie->b_index
    }

    return 0;
}

So you can basically keep the set of addresses of all the instances created and when checking the particular instance, just check if the current object address is in the set.

The idxElemSet can be also static inside IndexElement and the class itself might just provide static conversion function which does the check and conversion internally, etc.

EmDroid
  • 5,918
  • 18
  • 18