web-dev-qa-db-ja.com

1行で複数のオブジェクトポインターを宣言すると、コンパイラエラーが発生する

私がこれをするとき(私のクラスで)

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_eyessf::Spriteオブジェクトおよび/または参照。

なぜこれが機能しないのですか?宣言は同じではありませんか?

22
user569322

sf::Sprite* re_Sprite_hair, re_Sprite_body, re_Sprite_eyes;

3つのポインターを宣言しません-1つのポインターと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つの星を付ける必要があります。そのような場合、この状況を明確にするために、タイプではなく変数の側にスターを置くことを好みます。

51
Karthik T

CとC++の両方で、_*_は、型指定子ではなくdeclaratorにバインドします。どちらの言語でも、宣言はオブジェクトではなくのタイプに基づいています。

たとえば、intという名前のpへのポインタがあり、intが指すp値にアクセスするとします。そのためには、次のように、単項_*_演算子を使用してポインターを逆参照します。

_x = *p;
_

_*p_のタイプはintです。したがって、pの宣言は

_int *p;
_

これは、同じ宣言ステートメント内で宣言するポインターの数に関係なく当てはまります。 qrもポインタとして宣言する必要がある場合は、宣言子の一部として単項_*_も必要です。

_int *p, *q, *r;
_

_*q_および_*r_のタイプはintであるためです。 _T *p_、_T* p_、または_T * p_を記述できるのは、CおよびC++構文の偶然です。これらの宣言はすべてT (*p)として解釈されます。

これが、ポインタと参照型を次のように宣言するC++スタイルが好きでない理由です。

_T* p;
T& r;
_

これは、CおよびC++の宣言構文がどのように機能するかについての誤った見方を意味し、exactのような混乱を招くためです。ただし、そのスタイルdoesによってコードの意図がより明確になる場合があること、特にコンテナタイプを定義する場合があることを理解するのに十分なC++を書きました。

しかし、それはまだ間違っています。

16
John Bode

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

あなたの注意を引くかもしれないもう一つは、行です:

int * p1, * p2;

これは、前の例で使用された2つのポインターを宣言します。ただし、両方の型が*(intへのポインター)になるように、各ポインターにはアスタリスク(int*)があることに注意してください。これは、優先ルールのために必要です。代わりに、コードが次の場合は注意してください。

int * p1, p2;

p1は確かにint*型ですが、p2int型です。この目的では、スペースはまったく問題になりません。しかし、とにかく、ステートメントごとに複数のポインターを宣言することに関心のあるほとんどのポインターユーザーにとって、ポインターごとに1つのアスタリスクを置くことを覚えておけば十分です。またはさらに良い:変数ごとに異なるステートメットを使用します。

から http://www.cplusplus.com/doc/tutorial/pointers/

2
Robin Nag

アスタリスクは、ポインター変数名にバインドします。これを覚える方法は、C/C++では宣言が使用法を模倣していることに気づくことです。

ポインターは次のように使用できます。

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

同様に、

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

どちらの場合も、基礎となる型指定子と、式でその型のオブジェクトに「到達」するために必要な1つまたは複数の演算子があります。

1
Jive Dadson