Подтвердить что ты не робот

Попытка присвоить вектор 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 работает? Для меня это похоже на то же.

4b9b3361

Ответ 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;