Попытка присвоить вектор Base * из вектора Derived *
Это кажется довольно простой проблемой, но я не могу понять это. У меня есть std::vector
необработанных указателей на Производные объекты, и я просто хочу скопировать его в другой вектор базовых указателей с помощью оператора присваивания. С VС++ я получаю ошибку C2679 "binary '=': оператор не найден..." BTW Мне не нужна глубокая копия объектов, я просто хочу скопировать указатели. Пример кода:
#include <vector>
using namespace std;
struct Base{};
struct Derived: public Base {};
int main (int argc, char* argv[])
{
vector<Derived*> V1;
vector<Base*> V2;
V2 = V1; //Compiler error here
return 0;
}
Меня смущает то, что я могу скопировать вектор, перейдя через него и используя push_back
, например:
for (Derived* p_derived : V1)
V2.push_back(p_derived);
Итак, мой вопрос в том, почему назначение не работает, а push_back
работает? Для меня это похоже на то же.
Ответы
Ответ 1
Это потому, что в то время как Base
и Derived
имеют отношение, между vector<Base*>
и vector<Derived*>
нет отношения. Что касается иерархии классов, они полностью не связаны друг с другом, поэтому вы не можете назначить их другим.
Концепция, которую вы ищете, называется ковариация. В Java, например, String[]
является подтипом Object[]
. Но в С++ эти два типа являются только разными типами и не более связаны с String[]
и Bar
.
push_back
работает, потому что для этого метода требуется только T const&
(или T&&
), поэтому все, что конвертируется в Base*
, будет приемлемым - это a Derived*
.
Тем не менее, vector
имеет конструктор, который принимает пару итераторов, которые должны быть проще использовать здесь:
vector<Base*> v2(v1.begin(), v1.end());
Или, поскольку он уже построен:
v2.assign(v1.begin(), v1.end());
Ответ 2
push_back
выполняет элементарные преобразования. Оператор присваивания существует только между векторами того же типа.
Простое решение - использовать assign
:
v2.assign(v1.begin(), v1.end());
Ответ 3
В общем случае шаблонов, если у вас есть шаблон класса
template <typename T> struct Foo {};
Foo<Base>
не является базовым классом Foo<Derived>
.
Следовательно, вы не можете делать:
Foo<Derived> f1;
Foo<Base> f2 = f1;