命名空间
变体
操作

类声明

来自 cppreference.com
< cpp‎ | 语言
 
 
C++ 语言
一般主题
流程控制
条件执行语句
if
迭代语句(循环)
for
范围-for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 指定符
动态异常规范 (直到 C++17*)
noexcept 指定符 (C++11)
异常
命名空间
类型
类/结构体类型
联合类型

指定符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储持续时间指定符
初始化
 
 

类是用户定义的类型,由类说明符定义,类说明符出现在 decl-specifier-seq 中的 声明 语法中。

内容

[编辑] 语法

类说明符具有以下语法

class-key attr (可选) class-head-name final(可选) base-clause (可选) { member-specification } (1)
class-key attr (可选) base-clause (可选) { member-specification } (2)
1) 命名类定义
2) 匿名类定义
class-key - 以下之一: classstructunion。关键字 classstruct 除了默认的 成员访问 和默认的 基类访问 外,完全相同。如果是 union,则声明引入 联合类型
attr - (自 C++11 起) 任意数量的 属性,可能包含 alignas 指定符
class-head-name - 正在定义的类的名称,可选地进行 限定
final - (自 C++11 起) 如果存在,则该类 不能被派生
base-clause - 一个或多个基类的列表以及用于每个基类的继承模型(参见 派生类
member-specification - 访问说明符、成员对象和成员函数声明和定义的列表(参见下文

[编辑] 前向声明

以下形式的声明

class-key attr identifier ;

声明一个类类型,该类型将在该范围的后面定义。在定义出现之前,该类名称具有 不完整类型。这允许相互引用的类

class Vector; // forward declaration
 
class Matrix
{
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};
 
class Vector
{
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};

并且,如果特定源文件仅使用指向该类的指针和引用,这将有助于减少 #include 依赖关系

// In MyStruct.h
#include <iosfwd> // contains forward declaration of std::ostream
 
struct MyStruct
{
    int value;
    friend std::ostream& operator<<(std::ostream& os, const S& s);
    // definition provided in MyStruct.cpp file which uses #include <ostream>
};

如果前向声明出现在局部范围内,它将隐藏先前声明的类、变量、函数以及可能出现在封闭范围内的所有其他具有相同名称的声明

struct s { int a; };
struct s; // does nothing (s already defined in this scope)
 
void g()
{
    struct s; // forward declaration of a new, local struct "s"
              // this hides global struct s until the end of this block
 
    s* p; // pointer to local struct s
 
    struct s { char* p; }; // definitions of the local struct s
}

请注意,详细类型说明符 作为其他声明的一部分也可能引入新的类名称,但前提是 名称查找 找不到先前声明的具有相同名称的类。

class U;
 
namespace ns
{
    class Y f(class T p); // declares function ns::f and declares ns::T and ns::Y
 
    class U f(); // U refers to ::U
 
    // can use pointers and references to T and Y
    Y* p;
    T* q;
}

[编辑] 成员规范

成员规范,或类定义的主体,是由大括号包围的,包含任意数量以下内容的序列:

1) 形式为以下内容的成员声明
attr (可选) decl-specifier-seq (可选) member-declarator-list (可选) ;
attr - (自 C++11 起) 任意数量的 属性
decl-specifier-seq - 说明符 的序列。它仅在构造函数、析构函数和用户定义的类型 转换函数 的声明中是可选的。
member-declarator-list - 类似于 init-declarator-list,但另外允许 位域声明纯说明符、virt-说明符(overridefinal(自 C++11 起),并且不允许 直接非列表初始化语法

此声明可以声明 静态 和非静态 数据成员成员函数、成员 typedef、成员 枚举嵌套类。它也可以是 友元声明

class S
{
    int d1;             // non-static data member
    int a[10] = {1, 2}; // non-static data member with initializer (C++11)
 
    static const int d2 = 1; // static data member with initializer
 
    virtual void f1(int) = 0; // pure virtual member function
 
    std::string d3, *d4, f2(int); // two data members and a member function
 
    enum { NORTH, SOUTH, EAST, WEST };
 
    struct NestedS
    {
        std::string s;
    } d5, *d6;
 
    typedef NestedS value_type, *pointer_type;
};
2) 函数定义,它既声明又定义 成员函数友元函数。成员函数定义后的分号是可选的。在类主体内部定义的所有函数都自动 内联,除非它们附加到 命名模块(自 C++20 起)
class M
{
    std::size_t C;
    std::vector<int> data;
public:
    M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition
 
    int operator()(std::size_t r, std::size_t c) const // member function definition
    {
        return data[r * C + c];
    }
 
    int& operator()(std::size_t r, std::size_t c) // another member function definition
    {
        return data[r * C + c];
    }
};
3) 访问说明符 public:protected:private:
class S
{
public:
    S();          // public constructor
    S(const S&);  // public copy constructor
    virtual ~S(); // public virtual destructor
private:
    int* ptr; // private data member
};
4) 使用声明
class Base
{
protected:
    int d;
};
 
class Derived : public Base
{
public:
    using Base::d;    // make Base's protected member d a public member of Derived
    using Base::Base; // inherit all bases' constructors (C++11)
};
5) static_assert 声明
template<typename T>
struct Foo
{
    static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point");
};
6) 成员模板声明
struct S
{
    template<typename T>
    void f(T&& n);
 
    template<class CharT>
    struct NestedS
    {
        std::basic_string<CharT> s;
    };
};
7) 别名声明
template<typename T>
struct identity
{
    using type = T;
};
(自 C++11 起)
8) 成员类模板的推断指南
struct S
{
    template<class CharT>
    struct NestedS
    {
        std::basic_string<CharT> s;
    };
 
    template<class CharT>
    NestedS(std::basic_string<CharT>) -> NestedS<CharT>;
};
(自 C++17 起)
9) 使用枚举声明
enum class color { red, orange, yellow };
 
struct highlight
{
    using enum color;
};
(自 C++20 起)

[编辑] 局部类

类声明可以出现在函数主体内部,在这种情况下它定义一个局部类。这种类的名称仅在函数范围内存在,在函数外部无法访问。

  • 局部类不能有静态数据成员。
  • 局部类的成员函数没有链接。
  • 局部类的成员函数必须完全在类主体内部定义。
  • 局部类 除了 闭包类型(自 C++14 起) 不能有成员模板。
  • 局部类不能有 友元模板
  • 局部类不能在类定义内部定义 友元函数
  • 函数(包括成员函数)内部的局部类可以访问封闭函数可以访问的相同名称。
  • 局部类不能用作模板参数。
(直到 C++11)
#include <algorithm>
#include <iostream>
#include <vector>
 
int main()
{
    std::vector<int> v{1, 2, 3};
 
    struct Local
    {
        bool operator()(int n, int m)
        {
            return n > m;
        }
    };
 
    std::sort(v.begin(), v.end(), Local()); // since C++11
 
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

输出

3 2 1

[编辑] 关键字

classstructunion

[编辑] 缺陷报告

以下行为更改的缺陷报告被追溯应用于先前发布的 C++ 标准。

DR 应用于 已发布的行为 正确行为
CWG 1693 C++98 成员声明不能为空 允许空声明
CWG 1930 C++98 member-declarator-list 可以为空,当 decl-specifier-seq
包含存储类说明符或 cv 限定符
列表不能为空

[编辑] 另请参见

C 文档 for 结构声明