static members1

一个类的static member也称为"class variable", 这是因为它是该类所有对象中共享的,即它的值不会因所属该类对象的不同而发生改变。

它可以用于统计目前该类实例化了多少对象:

// static members in classes
#include <iostream>
using namespace std;

class Dummy {
  public:
    static int n;
    Dummy () { n++; };
};

int Dummy::n=0;

int main () {
  Dummy a;
  Dummy b[5];
  cout << a.n << '\n';
  Dummy * c = new Dummy;
  cout << Dummy::n << '\n';
  delete c;
  return 0;
}

6
7

由于static member的独特性,它禁止在类的内部被初始化2,因为类的定义主要用于描述如何创建其对象和行为。但是static member不和任何对象绑定,因此它们的初始化必须分别对待。同时类中的static member仅仅是告知编译器它的存在,但是并没有为其分配存储空间。综上,为了给static member分配存储空间并且进行初始化,我们需要在类的外部进行这个操作,即

int Dummy::n=0;

对于static member functions而言,它们与static member variables类似,它们是该类所有对象公有的。因为对象需要创建才存在,而non- static member是和object绑定的。所以static member functions禁止访问non-static member (neither member variables nor member functions),当然也无法在函数内部使用this关键字

Const member functions3

当一个类的对象被限定为const时,从类的外部访问其member data时仅能进行read-only,但constructor仍然被自动调用来初始化和修改对象的data。

// constructor on const object
#include <iostream>
using namespace std;

class MyClass {
  public:
    int x;
    MyClass(int val) : x(val) {}
    int get() {return x;}
};

int main() {
  const MyClass foo(10);
// foo.x = 20;            // not valid: x cannot be modified
  cout << foo.x << '\n';  // ok: data member x can be read
  return 0;
}

10

一个const限定的对象仅能调用其const限定的member functions。而限定member functions为const的方式为在参数列表后(),函数体前插入const关键字。例如:

int get() const {return x;}

值得注意的是,因为对象被const限定,因此我们无法修改此对象的state。而non-static members可能有修改其状态的风险,因此禁止const限定的member functions修改non-static data (可以访问)以及调用non-const member functions

此外,一个类可以根据constness来对其member functions进行重载。在这种情况下,仅有const限定的object可以调用const版本的member function,其他情况的object调用non-const member function。

// overloading members on constness
#include <iostream>
using namespace std;

class MyClass {
    int x;
public:
    MyClass(int val) : x(val) {}
    const int& get() const { cout << "const version" << endl; return x;}
    int& get() { cout << "non-const version" << endl; return x;}
};

int main() {
    MyClass foo (10);
    const MyClass bar (20);
    foo.get() = 15;         // ok: get() returns int&
// bar.get() = 25;        // not valid: get() returns const int&
    cout << foo.get() << '\n';
    cout << bar.get() << '\n';

    return 0;
}

non-const version
non-const version
15
const version
20


  1. https://legacy.cplusplus.com/doc/tutorial/templates/ ↩︎
  2. except for constexpr static members, which can be initialized inside the class since C++11 ↩︎
  3. https://legacy.cplusplus.com/doc/tutorial/templates/ ↩︎