訪問類成員

要訪問類物件的成員變數和成員函式,請使用 . 運算子:

struct SomeStruct {
  int a;
  int b;
  void foo() {}
};

SomeStruct var;
// Accessing member variable a in var.
std::cout << var.a << std::endl;
// Assigning member variable b in var.
var.b = 1;
// Calling a member function.
var.foo();

通過指標訪問類的成員時,通常使用 -> 運算子。或者,可以取消引用例項並使用 . 運算子,儘管這種情況不太常見:

struct SomeStruct {
  int a;
  int b;
  void foo() {}
};

SomeStruct var;
SomeStruct *p = &var;
// Accessing member variable a in var via pointer.
std::cout << p->a << std::endl;
std::cout << (*p).a << std::endl;
// Assigning member variable b in var via pointer.
p->b = 1;
(*p).b = 1;
// Calling a member function via a pointer.
p->foo();
(*p).foo();

訪問靜態類成員時,使用::運算子,但是使用類的名稱而不是它的例項。或者,可以使用 .-> 運算子分別從例項或指向例項的指標訪問靜態成員,其語法與訪問非靜態成員的語法相同。

struct SomeStruct {
  int a;
  int b;
  void foo() {}

  static int c;
  static void bar() {}
};
int SomeStruct::c;

SomeStruct var;
SomeStruct* p = &var;
// Assigning static member variable c in struct SomeStruct.
SomeStruct::c = 5;
// Accessing static member variable c in struct SomeStruct, through var and p.
var.a = var.c;
var.b = p->c;
// Calling a static member function.
SomeStruct::bar();
var.bar();
p->bar();

背景

-> 運算子是必需的,因為成員訪問運算子 . 優先於解除引用運算子*

人們會期望*p.a 會取消引用 p(導致對 p 指向的物件的引用),然後訪問其成員 a。但事實上,它試圖訪問 p 的成員 a,然後取消引用它。即*p.a 相當於*(p.a)。在上面的示例中,由於兩個事實,這將導致編譯器錯誤:首先,p 是一個指標,並且沒有成員 a。其次,a 是一個整數,因此不能被解除引用。

對這個問題不常見的解決方案是明確控制優先順序:(*p).a

相反,-> 運算子幾乎總是被使用。它是第一個取消引用指標然後訪問它的簡寫。即 (*p).ap->a 完全相同。

::運算子是作用域運算子,其使用方式與訪問名稱空間成員的方式相同。這是因為靜態類成員被認為是在該類的範圍內,但不被視為該類的例項的成員。由於歷史原因,靜態成員也允許使用普通的 .->,儘管他們不是例項成員; 這用於在模板中編寫通用程式碼,因為呼叫者不需要關心給定的成員函式是靜態的還是非靜態的。