web-dev-qa-db-de.com

Was ist der Unterschied zwischen "::" "." und "->" in c ++

Mögliches Duplikat:
Wann verwende ich einen Punkt, einen Pfeil oder einen Doppelpunkt, um auf Mitglieder einer Klasse in C++ zu verweisen?

Ich habe die Klasse Kwadrat erstellt und drei int-Felder im Inneren. Die Codeblöcke geben mir Hinweise, dass ich mit ::, . Und -> In das Feld des Objekts gelangen kann. Der Pfeil funktioniert nur, aber warum? Was ist der Unterschied zwischen diesen drei?

#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 .-> für den Zugriff auf Variablen und Methoden von Objektmitgliedern über pointer auf object

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

2 .. für den Zugriff auf Variablen und Methoden von Objektmitgliedern über das Objekt instance

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

3.:: für den Zugriff auf statische Variablen und Methoden eines class/struct oder namespace. Es kann auch verwendet werden, um auf Variablen und Funktionen aus einem anderen Bereich zuzugreifen (tatsächlich sind Klasse, Struktur, Namespace in diesem Fall Bereiche).

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

In C++ können Sie mit verschiedenen Operatoren auf Felder oder Methoden zugreifen, je nach Typ:

  • ClassName :: FieldName: öffentliches statisches Feld und Methoden der Klasse
  • ClassInstance.FieldName: Zugriff auf ein öffentliches Feld (oder eine Methode) über einen Klassenverweis
  • ClassPointer-> FieldName: Zugriff auf ein öffentliches Feld (oder eine Methode), das bzw. die einen Klassenzeiger dereferenziert

Beachten Sie, dass :: nicht mit einer Klasseninstanz, sondern mit einem Klassennamen verwendet werden sollte, da statische Felder oder Methoden allen Instanzen einer Klasse gemeinsam sind.

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

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

dann greifen Sie auf diesen Weg zu:

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

Ganz einfach ausgedrückt: :: Ist der Bereichsoperator, . Ist der Zugriffsoperator (ich vergesse, wie der tatsächliche Name lautet?) Und -> Ist der Dereferenzierungspfeil.

:: - Gültigkeitsbereich einer Funktion. Das heißt, der Compiler erfährt, in welcher Klasse sich die Funktion befindet und wie sie aufgerufen werden soll. Wenn Sie diesen Operator zum Aufrufen einer Funktion verwenden, ist die Funktion eine static -Funktion.

. - Ermöglicht den Zugriff auf eine Mitgliedsfunktion für ein bereits erstelltes Objekt. Beispielsweise ruft Foo x; x.bar() die Methode bar() für das instanziierte Objekt x mit dem Typ Foo auf. Sie können dies auch verwenden, um auf öffentliche Klassenvariablen zuzugreifen.

-> - Im Wesentlichen dasselbe wie ., Außer dass dies bei Zeigertypen funktioniert. Im Wesentlichen dereferenziert es den Zeiger und ruft dann . Auf. Dies ist äquivalent zu (*ptr).method()

16
RageD

Die drei Operatoren haben verwandte, aber unterschiedliche Bedeutungen, trotz der irreführenden Anmerkung der IDE.

Das ::-Operator ist als Bereichsauflösungsoperator bekannt und wird verwendet, um von einem Namespace oder einer Klasse zu einem ihrer Mitglieder zu gelangen.

Das . und -> -Operatoren dienen dem Zugriff auf die Mitglieder einer Objektinstanz und werden erst nach dem Erstellen einer Objektinstanz wirksam. Sie nutzen . wenn Sie ein aktuelles Objekt haben (oder einen Verweis auf das Objekt, deklariert mit & im deklarierten Typ), und Sie verwenden -> wenn Sie einen Zeiger auf ein Objekt haben (deklariert mit * im deklarierten Typ).

Das Objekt this ist immer ein Zeiger auf die aktuelle Instanz, weshalb das Objekt -> Operator ist der einzige, der funktioniert.

Beispiele:

// 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

Sie haben einen Zeiger auf ein Objekt. Daher müssen Sie auf ein Feld eines Objekts zugreifen, auf das der Zeiger zeigt. Um den Zeiger zu dereferenzieren, verwenden Sie *, und um auf ein Feld zuzugreifen, verwenden Sie ., damit Sie Folgendes verwenden können:

cout << (*kwadrat).val1;

Beachten Sie, dass die Klammern erforderlich sind. Diese Operation ist so verbreitet, dass sie vor langer Zeit (als C noch jung war) beschlossen haben, eine "Kurzform" zu erstellen:

cout << kwadrat->val1;

Diese sind als identisch definiert. Wie Sie sehen können, die -> kombiniert im Grunde nur ein * und ein . in einer einzigen Operation. Wenn Sie sich direkt mit einem Objekt oder einem Verweis auf ein Objekt befassen, können Sie das . ohne vorher einen Zeiger zu dereferenzieren:

Kwadrat kwadrat2(2,3,4);

cout << kwadrat2.val1;

Das :: ist der Operator für die Bereichsauflösung. Es wird verwendet, wenn Sie nur name qualifizieren müssen, sich aber überhaupt nicht mit einem einzelnen Objekt befassen. Dies wäre in erster Linie, um auf ein statisches Datenelement zuzugreifen:

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.

Da in diesem Fall xstatic ist, ist es keiner bestimmten Instanz von something zugeordnet. Tatsächlich ist es auch dann vorhanden, wenn keine Instanz dieses Objekttyps erstellt wurde. In diesem Fall können wir mit dem Bereichsauflösungsoperator darauf zugreifen:

something::x = 10;

std::cout << something::x;

Beachten Sie jedoch, dass es auch zulässig ist, auf ein statisches Element zuzugreifen, als wäre es ein Element eines bestimmten Objekts:

something s;

s.x = 1;

Zumindest, wenn Speicher dient, war dies zu Beginn der Geschichte von C++ nicht zulässig, aber die Bedeutung ist eindeutig, so dass sie beschlossen, es zuzulassen.

8
Jerry Coffin

Das '::' ist für statische Mitglieder.

2
Marcin Zaluski

-> ist für Zeiger auf eine Klasseninstanz

. ist für Klasseninstanzen

:: ist für Klassennamen - zum Beispiel bei Verwendung eines statischen Members

2
Gir

Andere haben die unterschiedlichen Syntaxen beantwortet, aber bitte beachten Sie, dass Sie bei der Ausführung Ihres couts nur -> Verwenden:

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