命名空间
变体
操作

static 成员

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
 
 

在类定义中,关键词 static 声明不绑定到类实例的成员。

在类定义之外,它有不同的含义:参见存储期

目录

[编辑] 语法

静态成员的声明是一个成员声明,其声明说明符包含关键词 static。关键词 static 通常出现在其他说明符之前(这就是为什么语法常被非正式地描述为 static 数据成员static 成员函数),但可以出现在说明符序列中的任何位置。

任何静态数据成员和静态成员函数的名称必须与包含该类的名称不同。

[编辑] 解释

类的静态成员不与类的对象关联:它们是具有静态或线程(C++11 起)存储期的独立变量,或者是常规函数。

关键词 static 仅用于在类定义内声明静态成员,而不用于定义该静态成员。

class X { static int n; }; // declaration (uses 'static')
int X::n = 1;              // definition (does not use 'static')

类体内的声明不是定义,并且可以声明成员为不完整类型(除了 void),包括声明该成员的类型。

struct Foo;
 
struct S
{
    static int a[]; // declaration, incomplete type
    static Foo x;   // declaration, incomplete type
    static S s;     // declaration, incomplete type (inside its own definition)
};
 
int S::a[10]; // definition, complete type
struct Foo {};
Foo S::x;     // definition, complete type
S S::s;       // definition, complete type

然而,如果声明使用 constexprinline(C++17 起) 说明符,则成员必须声明为完整类型。

(C++11 起)

要引用类 T 的静态成员 m,可以使用两种形式:限定名 T::m 或成员访问表达式 E.mE->m,其中 E 是一个分别评估为 TT* 的表达式。在同一类作用域内,无需限定。

struct X
{
    static void f(); // declaration
    static int n;    // declaration
};
 
X g() { return X(); } // some function returning X
 
void f()
{
    X::f();  // X::f is a qualified name of static member function
    g().f(); // g().f is member access expression referring to a static member function
}
 
int X::n = 7; // definition
 
void X::f() // definition
{
    n = 1; // X::n is accessible as just n in this scope
}

静态成员遵循类成员访问规则(private, protected, public)

[编辑] 静态成员函数

静态成员函数不与任何对象关联。调用时,它们没有 this 指针。

静态成员函数不能是 virtualconstvolatile引用限定的。

静态成员函数的地址可以存储在常规的函数指针中,但不能存储在成员函数指针中。

[编辑] 静态数据成员

静态数据成员不与任何对象关联。即使没有定义类的任何对象,它们也存在。在整个程序中,只有一个具有静态存储期的静态数据成员实例,除非使用关键词 thread_local,在这种情况下,每个线程有一个具有线程存储期的此类对象(C++11 起)

静态数据成员不能是 mutable 的。

如果类本身具有外部链接(不是未命名命名空间的成员),则命名空间作用域中的类的静态数据成员具有外部链接。局部类(在函数内部定义的类)和未命名类,包括未命名类的成员类,不能拥有静态数据成员。

静态数据成员可以声明为 inline。内联静态数据成员可以在类定义中定义,并可以指定初始化器。它不需要类外定义。

struct X
{
    inline static int fully_usable = 1; // No out-of-class definition required, ODR-usable
    inline static const std::string class_name{"X"}; // Likewise
 
    static const int non_addressable = 1; // C.f. non-inline constants, usable
                                          // for its value, but not ODR-usable
    // static const std::string class_name{"X"}; // Non-integral declaration of this
                                                 // form is disallowed entirely
};
(C++17 起)

[编辑] 常量静态成员

如果一个整型或枚举类型的静态数据成员被声明为 const(而不是 volatile),它可以在类定义中直接用初始化器初始化,其中每个表达式都是常量表达式

struct X
{
    const static int n = 1;
    const static int m{2}; // since C++11
    const static int k;
};
const int X::k = 3;

如果 LiteralType 的静态数据成员被声明为 constexpr,它必须在类定义中直接用初始化器初始化,其中每个表达式都是常量表达式。

struct X
{
    constexpr static int arr[] = { 1, 2, 3 };        // OK
    constexpr static std::complex<double> n = {1,2}; // OK
    constexpr static int k; // Error: constexpr static requires an initializer
};
(C++11 起)

如果 const 非 inline(C++17 起) 静态数据成员或 constexpr 静态数据成员(C++11 起)(C++17 前)ODR-used,仍需要在命名空间作用域提供定义,但它不能带有初始化器。

constexpr 静态数据成员隐式地是 inline,不需要在命名空间作用域重新声明。这种不带初始化器的重新声明(以前是必需的)仍然允许,但已弃用。

(C++17 起)
struct X
{
    static const int n = 1;
    static constexpr int m = 4;
};
 
const int *p = &X::n, *q = &X::m; // X::n and X::m are ODR-used
const int X::n;             // … so a definition is necessary
constexpr int X::m;         // … (except for X::m in C++17)

[编辑] 关键词

static

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
CWG 194 C++98 (静态)成员函数名可以与类名相同 添加了命名限制(包括
非静态成员函数)

[编辑] 参考

  • C++23 标准 (ISO/IEC 14882:2024)
  • 11.4.9 静态成员 [class.static]
  • C++20 标准 (ISO/IEC 14882:2020)
  • 11.4.8 静态成员 [class.static]
  • C++17 标准 (ISO/IEC 14882:2017)
  • 12.2.3 静态成员 [class.static]
  • C++14 标准 (ISO/IEC 14882:2014)
  • 9.4 静态成员 [class.static]
  • C++11 标准 (ISO/IEC 14882:2011)
  • 9.4 静态成员 [class.static]
  • C++98 标准 (ISO/IEC 14882:1998)
  • 9.4 静态成员 [class.static]

[编辑] 另请参见