web-dev-qa-db-ja.com

違いは何ですか "::" "。"およびC ++の「->」

可能性のある複製:
C++のクラスのメンバーを参照するためにドット、矢印、または二重コロンを使用するのはいつですか?

Kwadratというクラスを作成し、内部に3つのintフィールドがあります。コードブロックは、::.、および->によってオブジェクトのフィールドに入ることができるというアドバイスをくれます。矢印だけが機能するものですが、なぜですか?これら3つの違いは何ですか?

#include <iostream>

using namespace std;

class Kwadrat{
public:
int val1, val2, val3;
    Kwadrat(int val1, int val2, int val3)
    {
        this->val1 = val1;
        //this.val2 = val2;
        //this::val3 = val3;
    }
};

int main()
{
    Kwadrat* kwadrat = new Kwadrat(1,2,3);
    cout<<kwadrat->val1<<endl;
    cout<<kwadrat->val2<<endl;
    cout<<kwadrat->val3<<endl;
    return 0;
}
74
Yoda

1 .->pointerを介してオブジェクトにオブジェクトメンバー変数とメソッドにアクセスするため

Foo *foo = new Foo();
foo->member_var = 10;
foo->member_func();

2 ..オブジェクトを介してオブジェクトメンバー変数とメソッドにアクセスする場合instance

Foo foo;
foo.member_var = 10;
foo.member_func();

3 .::は、class/structまたはnamespaceの静的変数とメソッドにアクセスします。また、別のスコープ(実際にはクラス、構造体、名前空間はその場合のスコープです)から変数と関数にアクセスするために使用できます。

int some_val = Foo::static_var;
Foo::static_method();
int max_int = std::numeric_limits<int>::max();
152
Andrew

C++では、タイプに応じて異なる演算子を使用してフィールドまたはメソッドにアクセスできます。

  • ClassName :: FieldName:クラスpublic staticフィールドおよびメソッド
  • ClassInstance.FieldName:クラス参照を介してパブリックフィールド(またはメソッド)にアクセスする
  • ClassPointer-> FieldName:クラスポインターを参照解除するパブリックフィールド(またはメソッド)にアクセスする

静的フィールドまたはメソッドはクラスのすべてのインスタンスに共通しているため、クラスインスタンスではなくクラス名で::を使用する必要があることに注意してください。

class AClass{
public:
static int static_field;
int instance_field;

static void static_method();
void method();
};

次に、この方法でアクセスします。

AClass instance;
AClass *pointer = new AClass();

instance.instance_field; //access instance_field through a reference to AClass
instance.method();

pointer->instance_field; //access instance_field through a pointer to AClass
pointer->method();

AClass::static_field;  
AClass::static_method();
25
Heisenbug

非常に単純な::はスコープ演算子、.はアクセス演算子(実際の名前は忘れましたか?)、->は逆参照矢印です。

::-関数のスコープ。つまり、コンパイラーは、関数がどのクラスに属しているか、したがって、どのように呼び出すかをコンパイラーに知らせます。この演算子を使用して関数を呼び出す場合、関数はstatic関数です。

.-これにより、既に作成されたオブジェクトのメンバー関数にアクセスできます。たとえば、Foo x; x.bar()は、インスタンス化されたオブジェクトxのメソッドbar()を呼び出し、タイプはFooです。これを使用して、パブリッククラス変数にアクセスすることもできます。

->-.と基本的に同じことですが、これはポインター型で機能します。本質的には、.を呼び出すよりもポインタを逆参照します。これを使用することは(*ptr).method()と同等です

16
RageD

IDEからの誤解を招く記述にもかかわらず、3つの演算子は関連しているが異なる意味を持っています。

::演算子はスコープ解決演算子と呼ばれ、名前空間またはクラスからそのメンバーの1つに到達するために使用されます。

.および->演算子は、オブジェクトインスタンスのメンバーにアクセスするためのものであり、オブジェクトインスタンスの作成後にのみ機能します。実際のオブジェクト(または宣言された型で.で宣言されたオブジェクトへの参照)がある場合は&を使用し、オブジェクトへのポインターがある場合は->を使用します(宣言された型で*で宣言されています)。

thisオブジェクトは常に現在のインスタンスへのポインターであるため、->演算子のみが機能する理由です。

例:

// In a header file
namespace Namespace {
    class Class {
        private:
            int x;
        public:
            Class() : x(4) {}
            void incrementX();
    };
}

// In an implementation file
namespace Namespace {
    void Class::incrementX() {    // Using scope resolution to get to the class member when we aren't using an instance
        ++(this->x);              // this is a pointer, so using ->. Equivalent to ++((*this).x)
    }
}

// In a separate file lies your main method
int main() {
    Namespace::Class myInstance;   // instantiates an instance. Note the scope resolution
    Namespace::Class *myPointer = new Namespace::Class;
    myInstance.incrementX();       // Calling a function on an object instance.
    myPointer->incrementX();       // Calling a function on an object pointer.
    (*myPointer).incrementX();     // Calling a function on an object pointer by dereferencing first

    return 0;
}
8
Platinum Azure

オブジェクトへのポインターがあります。そのため、ポインターが指すオブジェクトのフィールドにアクセスする必要があります。 *を使用するポインターを逆参照し、フィールドにアクセスするには.を使用するため、次を使用できます。

cout << (*kwadrat).val1;

括弧が必要であることに注意してください。この操作は非常に一般的であり、かなり前(Cが若かった頃)に「速記」方法を作成することにしました。

cout << kwadrat->val1;

これらは同一であると定義されています。ご覧のとおり、->は基本的に*.を1つの操作に結合するだけです。オブジェクトまたはオブジェクトへの参照を直接扱っている場合、最初にポインターを逆参照せずに.を使用できます。

Kwadrat kwadrat2(2,3,4);

cout << kwadrat2.val1;

::はスコープ解決演算子です。 nameを修飾するだけで、個々のオブジェクトをまったく扱っていない場合に使用されます。これは、主に静的データメンバーにアクセスするためのものです。

struct something { 
    static int x; // this only declares `something::x`. Often found in a header
};

int something::x;  // this defines `something::x`. Usually in .cpp/.cc/.C file.

この場合、xstaticであるため、somethingの特定のインスタンスには関連付けられていません。実際、そのタイプのオブジェクトのインスタンスが作成されていなくても存在します。この場合、スコープ解決演算子を使用してアクセスできます。

something::x = 10;

std::cout << something::x;

ただし、特定のオブジェクトのメンバーであるかのように静的メンバーにアクセスすることも許可されていることに注意してください。

something s;

s.x = 1;

少なくともメモリが提供される場合、C++の歴史の初期にはこれは許可されませんでしたが、意味は明確なので、許可することにしました。

8
Jerry Coffin

「::」は静的メンバー用です。

2
Marcin Zaluski

->クラスインスタンスへのポインタ用

。クラスインスタンス用

::クラス名用-静的メンバーを使用する場合など

2
Gir

他の人はさまざまな構文に答えていますが、coutsを実行しているときは、->のみを使用していることに注意してください。

int main()
{
    Kwadrat* kwadrat = new Kwadrat(1,2,3);
    cout<<kwadrat->val1<<endl;
    cout<<kwadrat->val2<<endl;
    cout<<kwadrat->val3<<endl;
    return 0;
}
1
psynnott