他のC派生言語(JavaやC#など)からC++に移行すると、C++がクラスのメンバーを参照する3つの方法を持っていることが最初は非常にわかりにくいです:a::b
、a.b
、およびa->b
。これらの演算子のどれをいつ使用しますか?
(注:これは Stack OverflowのC++ FAQ へのエントリとなることを意図しています。このフォームでFAQを提供するというアイデアを批判したい場合、それから これをすべて開始したメタへの投稿 がそれを行う場所になります。その質問への回答は C++チャットルーム で監視され、ここでFAQアイデアはそもそも始まったので、あなたの答えはアイデアを思いついた人に読まれる可能性が非常に高いです。)
C++がクラスまたはクラスオブジェクトのメンバーにアクセスするために使用する3つの異なる演算子、つまり二重コロン::
、ドット.
、および矢印->
は、3つの異なるシナリオで使用されます常に明確に定義されています。これを知ることで、どのコードでも、それぞれa::b
、a.b
、またはa->b
を見るだけで、a
とb
についてすぐに多くを知ることができます。あなたが見ます。
a::b
は、b
がクラス(または名前空間)a
のメンバーである場合にのみ使用されます。つまり、この場合、a
は常にクラス(または名前空間)の名前になります。
a.b
は、b
がオブジェクト(またはオブジェクトへの参照)a
のメンバーである場合にのみ使用されます。したがって、a.b
の場合、a
は常にクラスの実際のオブジェクト(またはオブジェクトへの参照)になります。
a->b
は元々、(*a).b
の略記法です。ただし、オーバーロードできるメンバーアクセス演算子は->
のみであるため、a
がoperator->
をオーバーロードするクラスのオブジェクトである場合(このような一般的な型はスマートポインターおよび反復子です) 、その意味はクラスデザイナーが実装したものです。結論:a->b
では、a
がポインターである場合、b
はポインターa
が参照するオブジェクトのメンバーになります。ただし、a
がこの演算子をオーバーロードするクラスのオブジェクトである場合、オーバーロードされた演算子関数operator->()
が呼び出されます。
小さな活字:
class
、struct
、またはunion
として宣言された型は、「クラス型」と見なされます。したがって、上記は3つすべてを指します。T*&
)はめったに使用されません。Sbiのポイント3の代替案を提案する
a->b
は、a
がポインターの場合にのみ使用されます。これは、(*a).b
、b
が指すオブジェクトのa
メンバーの省略形です。 C++には、「通常の」ポインターとスマートポインターの2種類のポインターがあります。 A* a
などの通常のポインターの場合、コンパイラは->
を実装します。 std::shared_ptr<A> a
などのスマートポインターの場合、->
はshared_ptr
クラスのメンバー関数です。
理由:このFAQの対象読者はスマートポインターを書いていません。 ->
が実際にoperator->()
と呼ばれること、またはオーバーロードできる唯一のメンバーアクセスメソッドであることを知る必要はありません。
#include <iostream>
#include <string>
using namespace std;
class Human {
private:
int age;
public:
string name;
Human(int humanAge, string humanName)
: age(humanAge), name(std::move(humanName)) {}
void DoSomething() {
cout << age << endl;
}
static void DisplayAge(const Human& person) {
cout << person.age << endl;
}
// ...
};
int main() {
// Usage of Dot(.)
Human firstMan(13, "Jim"); // firstMan is an instance of class Human
cout << firstMan.name << endl; // accessing member attributes
firstMan.DoSomething(); // accessing member functions
// Usage of Pointer Operator (->)
Human* secondMan = new Human(24, "Tom");
cout << secondMan->name << endl; // accessing member attributes
secondMan->DoSomething(); // accessing member functions
cout << (*secondMan).name << endl; // accessing member attributes
(*secondMan).DoSomething(); // accessing member functions
// Usage of Double Colon (::)
Human::DisplayAge(firstMan);
firstMan.DisplayAge(firstMan); // ok but not recommended
secondMan->DisplayAge(firstMan); // ok but not recommended
delete(secondMan);
return 0;
}
上記のコーディング例から、次のことがわかります。
*ドット演算子(.
)を使用して、インスタンス(またはオブジェクト)からメンバー(属性および関数)にアクセスする
*ポインター演算子(->
)を使用して、オブジェクト(またはnew
によって作成された)へのポインターからメンバー(属性および関数)にアクセスする
*ダブルコロン(::
)を使用して、オブジェクトをハンドルとして使用せずに、クラス自体から静的メンバー関数にアクセスします。 [注:推奨されない.
または->
を使用して、インスタンスから静的メンバー関数を呼び出すこともできます]