La dichiarazione di più puntatori di oggetti su una riga causa l’errore del compilatore

quando faccio questo (nella mia class)

public: Entity() { re_sprite_eyes = new sf::Sprite(); re_sprite_hair = new sf::Sprite(); re_sprite_body = new sf::Sprite(); } private: sf::Sprite* re_sprite_hair; sf::Sprite* re_sprite_body; sf::Sprite* re_sprite_eyes; 

Tutto funziona bene Tuttavia, se cambio le dichiarazioni a questo:

 private: sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes; 

Ottengo questo errore del compilatore:

 error: no match for 'operator=' in '((Entity*)this)->Entity::re_sprite_eyes = (operator new(272u), (, ((sf::Sprite*)))) 

E poi dice che i candidati per re_sprite_eyes sono oggetti sf::Sprite e / o riferimenti.

Perché non funziona? Le dichiarazioni non sono le stesse?

    sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;

    Non dichiara 3 puntatori: è un puntatore e 2 oggetti.

    sf::Sprite* sfortunatamente non si applica a tutte le variabili dichiarate dopo, solo la prima. È equivalente a

     sf::Sprite* re_sprite_hair; sf::Sprite re_sprite_body; sf::Sprite re_sprite_eyes; 

    Vuoi fare:

    sf::Sprite *re_sprite_hair, *re_sprite_body, *re_sprite_eyes;

    Devi mettere una stella per ogni variabile. In questi casi preferisco mantenere la stella sul lato della variabile, piuttosto che sul tipo, per chiarire esattamente questa situazione.

    Sia in C che in C ++, il * lega al dichiaratore , non allo specificatore del tipo. In entrambe le lingue, le dichiarazioni sono basate sui tipi di espressioni , non sugli oggetti.

    Ad esempio, supponiamo di avere un puntatore a un int chiamato p e di accedere al valore int cui punta p ; lo fai diterferendo il puntatore con l’operatore unario * , in questo modo:

     x = *p; 

    Il tipo dell’espressione *p è int ; quindi, la dichiarazione di p è

     int *p; 

    Questo è vero indipendentemente dal numero di puntatori che dichiari all’interno della stessa dichiarazione; se anche q e r devono essere dichiarati come puntatori, allora devono anche avere l’unario * come parte del dichiaratore:

     int *p, *q, *r; 

    perché le espressioni *q *r hanno tipo int . È un incidente di syntax C e C ++ che puoi scrivere T *p , T* p o T * p ; tutte queste dichiarazioni saranno interpretate come T (*p) .

    Questo è il motivo per cui non mi piace lo stile C ++ di dichiarare puntatori e tipi di riferimento come

     T* p; T& r; 

    perché implica una visualizzazione errata di come funziona la syntax delle dichiarazioni C e C ++, portando al tipo esatto di confusione che hai appena sperimentato. Tuttavia, ho scritto abbastanza C ++ per capire che ci sono momentjs in cui quello stile rende l’intento del codice più chiaro, specialmente quando si definiscono i tipi di container.

    Ma è ancora sbagliato.

    In C ++ 11 hai una piccola soluzione, che potrebbe essere migliore di spostare gli spazi avanti e indietro:

     template using type=T; template using func=T*; // I don't like this style, but type i, j; works ok type i = new int{3}, j = new int{4}; // But this one, imho, is much more readable than int(*f)(int, int) = ... func f = [](int x, int y){return x + y;}, g = [](int x, int y){return x - y;}; 

    Un’altra cosa che potrebbe attirare la vostra attenzione è la linea:

     int * p1, * p2; 

    Questo dichiara i due puntatori usati nell’esempio precedente. Ma si noti che c’è un asterisco ( * ) per ogni puntatore, in modo che entrambi abbiano il tipo int* (puntatore a int). Questo è richiesto a causa delle regole di precedenza. Si noti che, se, invece, il codice era:

     int * p1, p2; 

    p1 sarebbe effettivamente di tipo int* , ma p2 sarebbe di tipo int . Gli spazi non hanno alcuna importanza per questo scopo. In ogni caso, ricordare semplicemente di mettere un asterisco per puntatore è sufficiente per la maggior parte degli utenti di puntatori interessati a dichiarare più puntatori per istruzione. O ancora meglio: usa un diverso statemet per ogni variabile.

    Da http://www.cplusplus.com/doc/tutorial/pointers/

    L’asterisco si lega al nome della variabile del puntatore. Il modo per ricordare questo è notare che in C / C ++, le dichiarazioni imitano l’uso.

    I puntatori potrebbero essere usati in questo modo:

     sf::Sprite *re_sprite_body; // ... sf::Sprite sprite_bod = *re_sprite_body; 

    Allo stesso modo,

     char *foo[3]; // ... char fooch = *foo[1]; 

    In entrambi i casi, esiste un identificatore di tipo sottostante e l’operatore o gli operatori necessari per “ottenere” un object di quel tipo in un’espressione.