当我这样做时(在我班上)
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;
一切正常。但是,如果我将声明更改为:
private:
sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;
我收到此编译器错误:
error: no match for 'operator=' in '((Entity*)this)->Entity::re_sprite_eyes = (operator new(272u), (<statement>, ((sf::Sprite*)<anonymous>)))
然后它说re_sprite_eyes
的候选人是sf::Sprite
个对象和/或引用。
为什么这不起作用?声明不一样吗?
答案 0 :(得分:48)
sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;
不声明3个指针 - 它是一个指针和2个对象。
遗憾的是, sf::Sprite*
不适用于它后面声明的所有变量,只是第一个。它相当于
sf::Sprite* re_sprite_hair;
sf::Sprite re_sprite_body;
sf::Sprite re_sprite_eyes;
你想这样做:
sf::Sprite *re_sprite_hair, *re_sprite_body, *re_sprite_eyes;
您需要为每个变量添加一颗星。在这种情况下,我更倾向于将恒星放在变量的一边,而不是类型,以使这种情况明确。
答案 1 :(得分:14)
在C和C ++中,*
绑定到声明符,而不是类型说明符。在这两种语言中,声明都基于表达式的类型,而不是对象。
例如,假设您有一个指向名为int
的{{1}}的指针,并且您想要访问p
指向的int
值;你通过使用一元p
运算符取消引用指针来实现这一点,如下所示:
*
表达式的类型 x = *p;
为*p
;因此,int
的声明是
p
无论你在同一个声明语句中声明多少指针,都是如此;如果int *p;
和q
也需要声明为指针,那么他们还需要将一元r
作为声明者的一部分:
*
因为表达式 int *p, *q, *r;
和*q
的类型为*r
。您可以编写int
,T *p
或T* p
,这是C和C ++语法的偶然事件。所有这些声明都将被解释为T * p
。
这就是为什么我不喜欢将指针和引用类型声明为C ++的样式
T (*p)
因为它暗示了C和C ++声明语法如何工作的错误视图,导致您刚刚遇到的完全类型的混淆。但是,我已经编写了足够多的C ++来实现有时候 样式使代码的意图更清晰,特别是在定义容器类型时。
但它仍然是错误的。
答案 2 :(得分:5)
在C ++ 11中,你有一个很好的小解决方法,这可能比来回移动空间更好:
template<typename T> using type=T;
template<typename T> using func=T*;
// I don't like this style, but type<int*> i, j; works ok
type<int*> i = new int{3},
j = new int{4};
// But this one, imho, is much more readable than int(*f)(int, int) = ...
func<int(int, int)> f = [](int x, int y){return x + y;},
g = [](int x, int y){return x - y;};
答案 3 :(得分:2)
可能引起你注意的另一件事是:
int * p1, * p2;
这声明了前一个例子中使用的两个指针。但请注意每个指针都有一个星号(
*
),以便两者都有类型int*
(指向int的指针)。由于优先规则,这是必需的。请注意,如果代码是:int * p1, p2;
p1
确实属于int*
类型,但p2
类型为int
。对于这个目的,空间根本不重要。但无论如何,只需记住每个指针放一个星号就足以让大多数指针用户对每个语句声明多个指针感兴趣。甚至更好:为每个变量使用不同的状态。
答案 4 :(得分:1)
星号绑定到指针变量名称。记住这一点的方法是注意在C / C ++中,声明模仿使用。
指针可能像这样使用:
sf::Sprite *re_sprite_body;
// ...
sf::Sprite sprite_bod = *re_sprite_body;
类似地,
char *foo[3];
// ...
char fooch = *foo[1];
在这两种情况下,都有一个基础类型说明符,以及在表达式中“获取”该类型对象所需的运算符。