-1

I have a base class and several classes derived from it. The base class has a typeID that all derived classes get assigned so I can differentiate. I wish to create a search function that looks through vector lists but using a generic vector::iterator. I am unable to static_cast to the base-class iterator though and I get the error above.

I have developed an alternative solution, however I would like to know what mechanic of the language is preventing me from doing this?

    class CItem {
    public:
        enum ItemType { enumed types here };

        CItem();
        CItem(const string Name, ItemType itemType, const float cost, const float weight);
        virtual ~CItem();
        CItem(const CItem &);
        CItem& operator=(const CItem &);

        int itemID() const { return m_itemID; }
        void itemID(const int id) { m_itemID = id; }

    protected:
        ItemType m_Type;
    };

    class CDerivedClassA: public CItem {
    public:
        CDerivedClassA() {};
        virtual ~CDerivedClassA() {};

    protected:

    private:
    };

class CDerivedClassB: public CItem {
public:
    CDerivedClassB() {};
    virtual ~CDerivedClassB() {};

protected:

private:
};

void CContainer::Search(ItemType it) {
    vector<CItem>::iterator iter;

    switch (it) {
        case IT_GENERAL:
            iter = m_GeneralItemList.begin();
            break;
        case IT_A:
            iter = (static_cast<vector<CItem>>(m_DerivedListA)).begin();
            break;
        case IT_B:
            iter = (static_cast<vector<CItem>>(m_DerivedListB)).begin();
            break;
    }
}
Caolan
  • 149
  • 2
  • 8
  • Sidenote: I also tried doing the same kind of static cast against the iterator itself and received a similar error. – Caolan Dec 03 '17 at 22:26
  • 1
    We don't know what `m_DerivedListA` or `m_DerivedListB` are so it's hard to say – Tas Dec 03 '17 at 22:27
  • I thought my description made it clear but here you go: vector m_DerivedListA; vector m_DerivedListB; – Caolan Dec 03 '17 at 22:32
  • 1
    You seem to have some [slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) going on there. In addition, your alternative solution creates a temporary copy and then sets `iter` to a dangling iterator into that temporary vector. – chris Dec 03 '17 at 22:33
  • 3
    [mcve] are always far more preferable. You'd be looking at 6 more lines basically: `struct CItem {}; struct m_DerivedListA : CItem {};` etc. Yes the descrptions are accurate, but what if you had made a mistake in the class declaration? Just because the error appears on the line, doesn't mean the actual fault is there. – Tas Dec 03 '17 at 22:35
  • chris, I did not present my alternative solution. What you see above is the code causing me the issues. Also it's a code snippet not a complete solution. Later I use the iter variable in the iteration loop. – Caolan Dec 03 '17 at 22:38
  • 1
    I see. I also messed up in not remembering that `std::vector` doesn't allow construction from other vector types. That's what's making the cast error out. A `vector` isn't convertible to a `vector`, and things would be worse if it were because the example would compile and leave you with dangling iterators. – chris Dec 03 '17 at 22:45
  • Ahhhh. It's a limitation of the data structure being used then... Okay. I have done static_cast and const_cast'ing in other places so I was more than a little annoyed by this... Is there a better structure I should use for this. Besides creating my own list class I mean. – Caolan Dec 03 '17 at 22:47
  • 1
    It's not uncommon to have covariant read-only list types (e.g., `List` in Kotlin, `IReadOnlyList` in C#). In C++, that would probably be closest to a view or a `const_iterator`. However, `const_iterator`s are not specified to be covariant, so you'd need something of your own. For example, a `polymorphic_list_view`, where a view into a list of `Derived*` could be converted to a view into a list of `Base*`. It can be hard to get working for general containers. The reason for the read-only requirement is that the safety around this conversion breaks down otherwise. See Java's covariant arrays. – chris Dec 03 '17 at 23:04

1 Answers1

1

A vector:: is going to lose derived type information (this is called slicing). All that will be left is the part of each instance that belongs to the base. If you need to handle both base and derived types (or merely multiple derived types) in a single container you will need to use a container of pointers rather than a container of instances.

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23