2015-05-15 6 views
11

Ho il codice seguente:Perché il valore di un puntatore-membro è sempre lo stesso per i diversi membri della stessa struttura?

#include <iostream> 
#include <string> 

using namespace std; 

struct foo_s { 
    string a; 
    string b; 
    string c; 
}; 

void print_field(foo_s* foo, string foo_s::* field) { 
    cout << "field: " << field << " - " << foo->*field << endl; 
} 

int main() { 
    foo_s my_foo = { 
     "a", 
     "b", 
     "c", 
    }; 

    print_field(&my_foo, &foo_s::a); 
    print_field(&my_foo, &foo_s::b); 
    print_field(&my_foo, &foo_s::c); 

    return 0; 
} 

La sua uscita è:

field: 1 - a                                                    
field: 1 - b                                                    
field: 1 - c 

Sto avendo un po 'di difficoltà a capire le specifiche di quello che sta succedendo nella funzione print_field(). Vale a dire:

  1. Qual è il tipo di field? Immagino sia pointer-to-string-foo_s-member
  2. Perché il valore di field è sempre lo stesso (1 in questo caso), tuttavia foo->*field produce risultati diversi?

Principalmente, sono sconcertato in # 2. Ho immaginato campo sarebbe stato un "offset" dall'inizio della struct e foo->*field sarebbe stato concettualmente equivalente a qualcosa come

char* ptr = static_cast<char*>(foo); 
ptrdiff_t offset = somehow_get_the_byte_offset_from_pointer_to_member(field); 
ptr = ptr[offset]; 
string result = *static_cast<string*>(ptr); 

ma che sembra essere fuori dal field s' valore non varia tra le chiamate. Cosa mi manca? In che modo esattamente questa operazione specifica è descritta dallo standard?

risposta

18

Non c'è sovraccarico per << per formattare il valore di un puntatore membro, quindi non si otterrà nulla di particolarmente utile se ci provi. C'è un sovraccarico per bool e i puntatori membri sono convertibili in bool, quindi questo è ciò che accade qui. Il puntatore non è nullo, quindi converte in true, che per impostazione predefinita è formattato come 1.

Per dimostrare ulteriormente, è possibile provare prima lo streaming boolalpha; quindi dovresti vedere true anziché 1.

+2

Wow, questo mi insegna a stare con la buona vecchia stampa, e se è solo perché la capisco meglio. – martin

+5

@martin: questo darà un comportamento indefinito se si tenta di stampare un puntatore membro. C++ I/O è almeno tipologico, se a volte confuso. –

+1

@martin Domanda divertente - quale specificatore di formato si intende utilizzare per il puntatore al membro? Non conosci nemmeno le dimensioni della cosa (generalmente). – Angew

7
  1. Il tipo di field è, come dici tu, un puntatore a un membro della foo_s di tipo std::string.

  2. Il valore di field è 1 in tutti questi casi, perché i puntatori agli Stati sono convertibili ad bool, così quando si uscita di loro, si ottiene un 1 perché non sono nulli.

Problemi correlati