La statement de varios punteros a objetos en una línea causa un error en el comstackdor

cuando hago esto (en mi clase)

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; 

Todo funciona bien Sin embargo, si cambio las declaraciones a esto:

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

Me sale este error del comstackdor:

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

Y luego dice que los candidatos para re_sprite_eyes son sf::Sprite objetos sf::Sprite y / o referencias.

¿Por qué esto no funciona? ¿No son las declaraciones lo mismo?

sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;

No declara 3 punteros, es un puntero y 2 objetos.

sf::Sprite* lamentablemente no se aplica a todas las variables declaradas a continuación, solo la primera. Es equivalente a

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

Quieres hacer:

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

Necesitas poner una estrella para cada variable. En tales casos, prefiero mantener la estrella del lado de la variable, en lugar del tipo, para aclarar exactamente esta situación.

Tanto en C como en C ++, * une al declarador , no al especificador de tipo. En ambos idiomas, las declaraciones se basan en los tipos de expresiones , no en objetos.

Por ejemplo, supongamos que tiene un puntero a una int llamada p , y desea acceder al valor int que p apunta a; lo hace desreferenciando el puntero con el operador unario * , así:

 x = *p; 

El tipo de la expresión *p es int ; por lo tanto, la statement de p es

 int *p; 

Esto es cierto sin importar cuántos punteros declare dentro de la misma statement de statement; si q y r también deben declararse como punteros, también deben tener el unario * como parte del declarador:

 int *p, *q, *r; 

porque las expresiones *q y *r tienen tipo int . Es un accidente de syntax C y C ++ que puede escribir T *p , T* p o T * p ; todas esas declaraciones se interpretarán como T (*p) .

Es por eso que no me gusta el estilo C ++ de declarar tipos de puntero y referencia como

 T* p; T& r; 

porque implica una visión incorrecta de cómo funciona la syntax de statement de C y C ++, lo que lleva al tipo exacto de confusión que acaba de experimentar. Sin embargo, he escrito suficiente C ++ para darme cuenta de que hay veces en que ese estilo hace que el bash del código sea más claro, especialmente cuando se definen tipos de contenedores.

Pero todavía está mal.

En C ++ 11 tiene una pequeña y agradable solución, que podría ser mejor que desplazar espacios hacia adelante y hacia atrás:

 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;}; 

Otra cosa que puede llamar su atención es la línea:

 int * p1, * p2; 

Esto declara los dos punteros utilizados en el ejemplo anterior. Pero observe que hay un asterisco ( * ) para cada puntero, para que ambos tengan el tipo int* (puntero a int). Esto es obligatorio debido a las reglas de precedencia. Tenga en cuenta que si, en cambio, el código fuera:

 int * p1, p2; 

p1 hecho sería de tipo int* , pero p2 sería de tipo int . Los espacios no importan en absoluto para este propósito. Pero de todos modos, basta con recordar poner un asterisco por puntero para la mayoría de los usuarios de punteros interesados ​​en declarar punteros múltiples por extracto. O incluso mejor: use un statemet diferente para cada variable.

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

El asterisco se une al nombre de la variable del puntero. La forma de recordar esto es notar que en C / C ++, las declaraciones imitan el uso.

Los punteros se pueden usar así:

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

Similar,

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

En ambos casos, existe un especificador de tipo subyacente, y el operador o los operadores deben “acceder” a un objeto de ese tipo en una expresión.