Приведение шаблонов в c ++ с производными классами - PullRequest
5 голосов
/ 26 января 2010
#include <vector>

struct A {int a;};
struct B : public A {char b;};

int main()
{
  B b;
  typedef std::pair<A*, A*> MyPair;
  std::vector<MyPair> v;
  v.push_back(std::make_pair(&b, &b)); //compiler error should be here(pair<B*,B*>)
  return 0;
}

Я не понимаю, почему это компилируется (может быть, кто-нибудь может предоставить подробное объяснение? Это связано с поиском имени?

Кстати, в Solaris, SunStudio12 не компилируется: error : formal argument x of type const std::pair<A*, A*> & in call to std::vector<std::pair<A*,A*> >::push_back(const std::pair<A*, A*> & ) is being passed std::pair<B*, B*>

Ответы [ 2 ]

13 голосов
/ 26 января 2010

std::pair имеет шаблон конструктора:

template<class U, class V> pair(const pair<U, V> &p);

"Эффекты: инициализирует элементы из соответствующих членов аргумента, выполняя неявные преобразования при необходимости." (С ++ 03, 20.2.2 / 4)

Неявное преобразование из указателя производного класса в указатель базового класса.

0 голосов
/ 26 января 2010

Поскольку B является производным от A, вектор v будет содержать указатели на структуры базового класса объекта b. следовательно, вы можете получить доступ к членам A, т.е.

std::cout << v[0].first->a;

EDIT: Моя ошибка, как указано ниже, вы все равно можете приводить к указателям типа B, поскольку вектор состоит из указателей, а не объектов, поэтому срезы объектов не происходили.

вызов, такой как

std::cout << v[0].first->b; 

не будет компилироваться, поскольку элементы в векторе являются указателями базового класса и не могут указывать на производные члены класса без приведения, то есть

 std::cout << static_cast<B*>(v[0].first)->b; 

Также обратите внимание, что динамическое приведение, как в

std::cout << dynamic_cast<B*>(v[0].first)->b;  

не скомпилируется со следующей ошибкой в ​​gcc:

cast.cpp:14: error: cannot dynamic_cast ‘v.std::vector<_Tp, _Alloc>::operator[] [with _Tp = std::pair<A*, A*>, _Alloc = std::allocator<std::pair<A*, A*> >](0u)->std::pair<A*, A*>::first’ (of type struct A*’) to type struct B*’ (source type is not polymorphic)
...