2013-06-24 2 views
4

У меня есть полиморфная проблема.Прохождение полиморфных векторов

void func(std::vector< BaseClass* > A){} 

std::vector< SubClass* > B; 

func(B); //Compile error C2664 

Я получаю сообщение об ошибке, как так:

error C2664 'func' : cannot convert parameter from 'std::vector<_Ty>' to 'std::vector<_Ty>' with 
[ 
    _Ty=B * 
] 
and 
[ 
    _Ty=A * 
] 

Я также попробовал некоторые странные вещи, как у параметра будет указатель на вектор, и я передаю адрес вектора следующим образом:

void func(std::vector< BaseClass* > *A){} 

std::vector< SubClass* > B; 
func(&B); //same error 
+2

Вы ожидаете, что сможете передать 'vector ' функции, ожидающей 'vector '? Готов поспорить, вы бы этого не сделали. Это то же самое в вашем случае, действительно - типы не связаны. – jrok

+1

Зачем вам нужен std :: vector ? Вы всегда можете поместить SubClass * в BaseClass *. – WiSaGaN

ответ

10

Полиморфного вектора нет. std::vector и каждый другой тип контейнера в C++, включая . Макеты типов C всегда содержат ровно один тип. И факт состоит в том, что два разных контейнера имеют типы, которые связаны с , и не делают типы контейнеров связанными каким-либо образом.

В вашем случае, вы, возможно, придется построить второй вектор:

func(std::vector< BaseClass* >(B.begin(), B.end())); 

Обратите внимание, что пытается использовать std::vector<DerivedClass*> как std::vector<BaseClass*>, скажем, используя reinterpret_cast, является неопределенное поведение, и может не работать. Нет никакой гарантии, что фактический физический адрес подобъекта BaseClass в a DerivedClass объект имеет тот же самый физический адрес, что и .

+0

Обратите внимание, что OP, похоже, работает по-другому, у них есть вектор 'Base *' и попытайтесь получить вектор 'Derived *'. – jrok

+0

@jrok Перечитайте его публикацию. У него есть вектор 'B' типа' DerivedClass * ', и он хочет вызвать функцию' func', которая принимает вектор 'BaseClass *'. –

+0

Вы правы, я вижу вещи. Извините за прослушивание ya :) – jrok

6

Шаблоны к спасению:

template<typename T> 
void func(std::vector<T> A) 
{ 
    ... 
} 
+0

Это теряет безопасность типа (заменяет статический тип проверки на утиную печать, и в результате возникают очень странные сообщения об ошибках, если вы передаете недопустимый тип), и требует помещать реализацию 'func' в файл заголовка, увеличивая связь. Это нормально, если 'func' очень прост и очень стабилен, но в противном случае его следует избегать. –

+0

Почему я не могу принять все 3 ответа? .. все ответы полезны для меня –

5

Тот факт, что thisесть-that вовсе не означает, что коллекция из this является коллекция из that.

Рассмотрим, что может произойти, если то, что вы хотели было разрешено:

void func(std::vector<BaseClass*>& A) 
{ 
    A.push_back(new BaseClass); 
} 

std::vector<SubClass*> B; 

func(B); 

Oops! B теперь содержит что-то, что не является указателем на SubClass, а программа, которая разыменовывает, не определена.

Вам необходимо сделать копию с правильным шрифтом, использовать шаблоны или рефакторировать, чтобы вам не нужно было проходить коллекцию.

+0

Очень хорошая точка относительно типа безопасности. (Есть технические причины, по которым он не реализуется, независимо от типа безопасности, но проблема безопасности типа означает, что он не должен быть реализован, даже если это было возможно.) –

+0

Почему я не могу принять все 3 ответа? .. все ответы полезны для меня –

Смежные вопросы