2010-01-26 14 views
5
#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; 
} 

Non capisco perché questo compila (forse qualcuno può gentilmente fornire spiegazione dettagliata? E 'qualcosa legato al nome di look-up?C++ template fusione con le classi derivate

Btw, su Solaris, SunStudio12 esso non compila: 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*>

+4

Quel modello di struttura sopra non sta davvero facendo molto è? – BenG

+0

@BennyG: Ha sentito dei problemi nel quartiere e ha deciso di venire a dare un'occhiata. –

+0

scusate, cancellato – yurec

risposta

13

std::pair ha un modello di costruttore:

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

"Effects: Inizializza membri dai corrispondenti membri dell'argomento, eseguendo conversioni implicite come necessario." (C++ 03, 20.2.2/4)

conversione da un puntatore classe derivata da un puntatore alla classe base è implicito.

+1

+1 per una risposta breve e precisa :-) –

+0

Non sono convinto, make_pair è una funzione template, che deduce i tipi dagli argomenti. Destra? – yurec

+2

Sì, e crea una 'std :: pair (B *, B *)'. Quindi usa il costruttore sopra per costruire un 'std :: pair (A *, A *)' fuori da esso. – GManNickG

0

Poiché B è derivato da A, il vettore v conterrà i puntatori alle strutture di base della base dell'oggetto b. Pertanto, è possibile accedere ai membri di A, vale a dire

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

EDIT: Il mio errore, come sottolineato di seguito, è ancora possibile lanciare ai puntatori di tipo B dal momento che il vettore è di puntatori, non oggetti, quindi non l'affettamento dell'oggetto si è verificato.

Una chiamata come

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

non verrà compilato in quanto gli elementi nel vettore sono puntatori alla classe base e non possono indicare i membri della classe derivate senza cast, cioè

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

noti inoltre che un cast dinamico, come in

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

non verrà compilato con il seguente errore in 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) 
+2

I membri della classe B non sono stati persi e il tipo dinamico degli oggetti puntati è ancora B. È ancora possibile accedere ai membri di B: 'static_cast (v [0] .prima) -> b' (sebbene in In questo caso, un 'dynamic_cast' sarebbe probabilmente preferibile). –

+0

@tmatth: come dice James McNellis, puoi ancora accedere ai membri della classe derivati ​​tramite un cast. Forse stai pensando all'affinamento degli oggetti? Ciò si verifica solo quando si utilizza un vettore di oggetti ('A'), non un vettore di puntatori (' A * '). In tal caso, si, i membri di 'B' saranno scartati in silenzio. –

+0

ho modificato per riflettere il tuo feedback, si spera che questo chiarisca tutto. – tmatth

Problemi correlati