#c #c 11
#c #c 11
Вопрос:
У меня есть вектор, который содержит набор общих указателей:
std::vector<std::shared_ptr<Derived>> originalVector;
В какой-то момент он был приведен к Base
общим указателям, это выглядит как:
std::vector<std::shared_ptr<Base>>* castedVector = reinterpret_cast<std::vector<std::shared_ptr<Base>>*>(amp;originalVector);
Как добавить Derived
элемент в приведенный вектор? По-видимому, я могу поместить в него пустой std::shared_ptr
, знает ли этот новый общий указатель что-либо о типе, который он содержит, может ли он создать объект этого типа?
Обновление: Невозможно создать исходный объект после shared_ptr
приведения к базовому классу. После приведения он теряет всю информацию об исходном базовом типе. Более того: это reinterpret_cast
неопределенное поведение.
Комментарии:
1. В C нет «неявных приведений». Существуют неявные преобразования. Приведение — это выражение, которое программист явно записывает для запроса преобразования. И преобразование в вашем примере никогда не произойдет неявно. Приведение наверняка было.
2. @StoryTeller Да, вы правы, я только что привел этот вектор к базе, взломал, но работает. Вопрос все еще присутствует, по-видимому, {std::shared_ptr} не имеет никакой фабрики, но что, если это так)))
3. «взломать, но работает» — очень опасный взлом. coliru.stacked-crooked.com/a/20a276a9b5a1a7ae — Неопределенное поведение не определено.
4. @user1810087 просто
static_cast
я добавляю это к вопросу5. Единственная причина, по которой я упомянул UB, заключается в том, что это похоже на вопрос XY . Я полагаю, что вы пропустили шаг в описании вашей проблемы.
Ответ №1:
Вы должны иметь возможность добавлять указатель производного класса к вектору указателей базового класса. Затем производный указатель преобразуется в базовый указатель. Это вроде как не зависит от того, что делают интеллектуальные указатели. Не имеет значения, был ли вектор создан как вектор базовых элементов или он был преобразован в такой, не так ли?
std::vector<std::shared_ptr<Base>> bases;
// Create a Derived instance
auto derived = std::make_shared<Derived>();
bases.push_back(derived);
// Only create a pointer (might as well just create a Base pointer)
std::shared_ptr<Derived> emptyPointer;
bases.push_back(emptyPointer)
Комментарии:
1. Это было бы слишком просто, у меня нет type в этот момент (только Base), поэтому я не могу вызвать std::make_shared.
2. Первоначально вектор был создан как
std::vector<std::shared_ptr<Derived>>
затем приведен кstd::vector<std::shared_ptr<Base>>*
3. Если вы не можете создать экземпляр объекта, вы также можете просто создать объект shared_ptr<Производный> и добавить его в вектор (отредактированный ответ). Но вы должны быть очень осторожны, потому что доступ к этому указателю, конечно, приводит к ошибкам доступа… Я все еще не совсем уверен в том, чего вы пытаетесь достичь 🙂
4. Опять же, для вызова
shared_ptr<Derived>
мне нужен тип, я могу создать только пустойstd::shared_ptr
, мне нужно как-то создать объект для него, не зная типа.5. Если вы не знаете тип, как вы узнаете, что он наследуется от Base?
Ответ №2:
std::vector<std::shared_ptr<Base>>* castedVector =
reinterpret_cast<std::vector<std::shared_ptr<Base>>*>(amp;originalVector);
Это неопределенное поведение, не делайте этого.
Вы можете создать vector
набор указателей на базу путем копирования, а не путем лжи системе типов:
std::vector<std::shared_ptr<Base>> baseVector(originalVector.begin(), originalVector.end());
Это содержит копии исходных указателей, которые разделяют с ними права собственности, но содержащиеся указатели являются Base*
верхними Derived*
.
Очевидно, что если вы вставите новое значение в originalVector
, оно не будет в baseVector
, поэтому вам нужно будет создать новую копию всего originalVector
или вставить его в оба одновременно.