解決済み: C++ での式にはクラス型エラーが必要です

Shikha Chaudhary 2023年10月12日
  1. 解決済み: C++ での式にはクラス型エラーが必要です
  2. C++ での Expression Must Have Class Type エラーの原因
  3. C++ での Expression Must Have Class Type エラーの修正
  4. まとめ
解決済み: C++ での式にはクラス型エラーが必要です

C++ では、ドット (.) 演算子が直接メンバー選択に使用され、一方、矢印 (->) 演算子は間接メンバー選択に使用されます。 これらの演算子はどちらも意味がありますが、どこでどのように使用するかに注意する必要があります。

これは通常、オブジェクトが new 演算子を使用してインスタンス化されているかどうかによって異なります。 これについては後で説明しますが、とりあえず、expression must have class type エラーは、ドット (.) 演算子の不適切な使用から発生する C++ エラーの 1つであることを知っておいてください。

これがなぜ起こるのか、そしてそれを解決する方法を見てみましょう。

解決済み: C++ での式にはクラス型エラーが必要です

問題文をよりよく理解するには、以下のコードを見てください。 ここでは、関数 desert() を内部に持つ Deserts というクラスがあります。

main ブロックでは、Deserts クラスへのポインター d を定義し、ポインター d でドット (.) 演算子を使用して、クラス メソッド desert() にアクセスします。 しかし、このコードを実行するとエラーが発生します。

#include <iostream>
using namespace std;

class Deserts {
 public:
  void desert() { cout << "Have a cake!" << endl; }
};

int main() {
  Deserts *d = new Deserts();
  d.desert();
}

出力:

In function 'int main()':
error: request for member 'desert' in 'd', which is of pointer type 'Deserts*' (maybe you meant to use '->' ?)
   15 |     d.desert();
      |       ^~~~~~

これは、ドット (.) 演算子が正しく使用されていないために発生します。 より明確にするために、ドット (.) 演算子の基本を簡単に再検討しましょう。

C++ のドット (.) 演算子

C++ のドット (.) 演算子は、オブジェクトの属性とメソッドにアクセスするために使用されます。 つまり、オブジェクト名による直接メンバー選択に使用されていると言えます。

構文:

object_name.member_name;

以下は、ドット (.) 演算子が C++ でどのように機能するかを示す例です。 ここでは、2つのメンバーを持つ Desert という構造体があります。

main ブロック内で、オブジェクト d を作成し、構造体の 2つのメンバーに値を割り当てます。 ここで、オブジェクト d のメンバーの値を出力するために、12 行目と 13 行目でわかるように、ドット (.) 演算子を使用します。

これは基本的に、ドット (.) 演算子が C++ でどのように機能するかです。

C++ のドット (.) 演算子の詳細については、この リンクを参照してください。

#include <iostream>
using namespace std;

struct Desert {
  int cookie, cake;
};

int main() {
  struct Desert d = {10, 2};

  cout << "Cookies present:" << d.cookie << endl;  // use dot operator
  cout << "Cakes present  :" << d.cake << endl;    // use dot operator

  return 0;
}

出力:

Cookies present:10
Cakes present  :2

少し考えてみてください。前のコードのエラーの原因を特定できますか? もしそうなら、あなたに敬意を表します。

そうでない場合は、読み進めてください!

C++ での Expression Must Have Class Type エラーの原因

expression must have class type エラーは、通常はオブジェクトのメンバーにアクセスするために使用されるドット (.) 演算子がオブジェクトへのポインターで使用されるときに発生します。 このように考えてください。

オブジェクトへのポインターでドット (.) 演算子を使用します。 これで、通常どおりに動作して、ドット (.) 演算子がポインター メンバー (フィールドまたはメソッド) を見つけようとします。

クラスへのオブジェクトとクラスへのポインタは 2つの異なるものであることは常識です。 クラスへのオブジェクトを作成すると、クラス メンバーもオブジェクトの一部になりますが、クラスへのポインターを定義すると、これは起こりません。

したがって、ポインタは存在すらしていないものを見つけようとしていると言えますか?

そのとおりです。そのため、エラーが発生します。

C++ での Expression Must Have Class Type エラーの修正

C++ の expression must have class type error は 2つの方法で修正できます。 それらについて1つずつ説明しましょう。

New 演算子を使用せずにオブジェクトを初期化して C++ のクラス型エラーを解決する

new 演算子を使用してオブジェクトを初期化する場合、以下に示すようにポインターを使用します。

class *object = new class();

したがって、最初のオプションは、次のように new 演算子を使用せずにオブジェクトを初期化してポインターを削除することです。

class object;

ここで、この変更を加えて問題のあるコードを再実行してみましょう。 今回は、new 演算子を使用せずにオブジェクトをインスタンス化し、コードは正常に実行されます。

#include <iostream>
using namespace std;

class Deserts {
 public:
  void desert() { cout << "Have a cake!" << endl; }
};

int main() {
  Deserts d;  // Instantiate the object without using the new operator
  d.desert();
}

出力:

Have a cake!

しかし今、new 演算子を使用せずにオブジェクトをインスタンス化することが正しいことなのか疑問に思うかもしれません。 そうですね。

new 演算子を使用してオブジェクトを初期化すると、削除するまでメモリに残ります。 ただし、new 演算子を使用しない場合、オブジェクトはスコープ外になると破棄されます。

したがって、必要に応じて new 演算子を使用するかどうかを選択するのはあなた次第です。 ただし、new 演算子を使用すると、ドット (.) 演算子を使用してオブジェクト メンバーにアクセスするとエラーが発生することに注意してください。

その場合、次のセクションで説明するように、ドット (.) 演算子の代わりに矢印 (->) 演算子を使用する必要があります。

矢印 (->) 演算子を使用して C++ のクラス タイプ エラーを解決する

矢印 (->) 演算子は、ポインターを使用してオブジェクトのメンバーにアクセスするために使用されます。 つまり、矢印 (->) 演算子は、ポインターを介した間接的なメンバー選択に使用されます。

したがって、new 演算子を使用してオブジェクトをインスタンス化する場合、次のようにドット (.) 演算子を使用しないでください。

pointer_to_object.class_member;

むしろ、ポインターが関係しているため、次のように矢印 (->) 演算子を使用する必要があります。

pointer_to_object->class_member;

問題のあるコードにこの変更を加えて、再実行してみましょう。 今度はコードが正常に実行されることがわかります。

#include <iostream>
using namespace std;

class Deserts {
 public:
  void desert() { cout << "Have a cake!" << endl; }
};

int main() {
  Deserts *d = new Deserts();
  d->desert();  // use arrow operator to access the object member via pointer
}

出力:

Have a cake!

矢印 (->) 演算子を使用することは、次の表記法を簡略化したものであることに注意してください。

(*pointer_to_object).class_member

これが何を意味するのか理解できますか?

ドット (.) 演算子はポインターではなくオブジェクトと参照に対して使用されるため、ポインター型を逆参照する必要があります。まず、オブジェクトの参照を取得します。 次に、それをドット (.) 演算子と共に使用して、オブジェクト メンバーにアクセスできます。

しかし、これを行うより良い方法は、短くてきれいな矢印 (->) 演算子を使用することです。

C++ のアロー (->) 演算子の詳細については、この ドキュメントを参照してください。

まとめ

この記事では、C++ の expression must have class type エラーについて説明しました。 このエラーが発生する理由と、それを修正するためのさまざまな解決策について説明しました。

関連記事 - C++ Error