как обратиться к производному классу базового класса? - PullRequest
0 голосов
/ 31 октября 2018
class Element { };
class Container {
    vector<Element*> elements;
};

Выше приведен оригинальный код. Мне сказали не менять вышеуказанный код. Теперь у меня есть

class IndexElement: public Element {
    int b_index;
};

class Container* ctr;

Теперь у меня есть ctr->elements. Но Element не имеет члена b_index. Любой простой способ перенаправить атрибуцию elements с Element на IndexElement? Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Ну, даже без виртуального и RTTI (динамического приведения) у вас все еще есть возможность отслеживать и проверять созданные экземпляры IndexElement, например:

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;
}

Таким образом, вы можете в основном сохранить набор адресов всех созданных экземпляров, а при проверке конкретного экземпляра просто проверить, находится ли текущий адрес объекта в наборе.

idxElemSet также может быть статическим внутри IndexElement, а сам класс может просто обеспечивать функцию статического преобразования, которая выполняет проверку и преобразование внутри и т. Д.

0 голосов
/ 31 октября 2018

У вас есть один вариант: вы знаете , что у вас есть IndexElement, а не Element в векторе, и тогда вы можете использовать static_cast<IndexElement*>(elements[i]);. Имейте в виду, что если у вас нет только IndexElement, то это полностью сломается.

Если вы можете изменить b, то у вас есть другой вариант, сделав b виртуальным. Если вы не знаете, у вас может быть Element с и IndexElement с, и в этом случае используйте dynamic_cast<IndexElement*>(elements[i]); и проверьте его, в результате получите nullptr или нет. В этом случае b должен быть виртуальным (следовательно, виртуальным деструктором).

(я предполагаю, что мы находимся в Container, поэтому прямой доступ к его членам)

Полная пробная версия (которая прекратится из-за отсутствия выделенного 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;
}
...