C++ 参考手册
- C++11
- C++14
- C++17
- C++20
- C++ 编译器支持情况表
- 独立与宿主实现
- C++ 语言
- 变量模板(C++14 起)
- 整数字面量
- 聚合初始化
- 比较运算符
- 默认比较(C++20 起)
- 转义序列
- for 循环
- while 循环
- 用户定义转换
- SFINAE
- 主函数
- ASCII 码表
- 标识符
- 类型
- 内存模型
- 对象
- 基本概念
- 表达式
- 声明
- 初始化
- 函数
- 语句
- 类
- 运算符重载
- 模板
- 异常
- 事务性内存
- 占位符类型说明符 (C++11 起)
- decltype 说明符
- 函数声明
- final 说明符 (C++11 起)
- override 说明符(C++11 起)
- 引用声明
- 移动构造函数
- 移动赋值运算符
- 枚举声明
- constexpr 说明符(C++11 起)
- 列表初始化 (C++11 起)
- 构造函数与成员初始化器列表
- using 声明
- nullptr,指针字面量
- 基础类型
- 类型别名,别名模版 (C++11 起)
- 形参包
- 联合体声明
- 字符串字面量
- 用户定义字面量 (C++11 起)
- 属性说明符序列(C++11 起)
- Lambda 表达式 (C++11 起)
- noexcept 说明符 (C++11 起)
- noexcept 运算符 (C++11 起)
- alignof 运算符(C++11 起)
- alignas 说明符 (C++11 起)
- 存储类说明符
- 基于范围的 for 循环 (C++11 起)
- static_assert 声明
- 隐式转换
- 代用运算符表示
- 自增/自减运算符
- 折叠表达式(C++17 起)
- 类模板实参推导(C++17 起)
- 模板形参与模板实参
- if 语句
- inline 说明符
- 结构化绑定声明 (C++17 起)
- switch 语句
- 字符字面量
- 命名空间
- 求值顺序
- 复制消除
- consteval 说明符 (C++20 起)
- constinit 说明符 (C++20 起)
- 协程 (C++20)
- 模块 (C++20 起)
- 约束与概念 (C++20 起)
- new 表达式
- do-while 循环
- continue 语句
- break 语句
- goto 语句
- return 语句
- 动态异常说明
- throw 表达式
- try 块
- 命名空间别名
- 类声明
- cv(const 与 volatile)类型限定符
- 默认初始化
- 值初始化(C++03 起)
- 零初始化
- 复制初始化
- 直接初始化
- 常量初始化
- 引用初始化
- 值类别
- C++ 运算符优先级
- 布尔字面量
- 浮点字面量
- typedef 说明符
- 显式类型转换
- static_cast 转换
- dynamic_cast 转换
- const_cast 转换
- reinterpret_cast 转换
- delete 表达式
- 构造函数与成员初始化器列表
- this 指针
- 访问说明符
- 友元声明
- virtual 函数说明符
- explicit 说明符
- 静态成员
- 默认构造函数
- 复制构造函数
- 复制赋值运算符
- 析构函数
- 类模板
- 函数模板
- 显式(全)模板特化
- 汇编声明
- C++ 的历史
- 作用域
- 生存期
- 定义与单一定义规则(ODR)
- 名字查找
- 有限定的名字查找
- 无限定的名字查找
- 如同规则
- 未定义行为
- 翻译阶段
- 常量表达式
- 赋值运算符
- 算术运算符
- 逻辑运算符
- 成员访问运算符
- 其他运算符
- sizeof 运算符
- typeid 运算符
- 指针声明
- 数组声明
- 语言链接
- 详述类型说明符
- 默认实参
- 变长实参
- 实参依赖查找
- 重载决议
- 重载函数的地址
- 注入类名
- 非静态数据成员
- 非静态成员函数
- 嵌套类
- 派生类
- 空基类优化
- 抽象类
- 位域
- 转换构造函数
- 成员模板
- 模板实参推导
- 部分模板特化
- sizeof... 运算符
- 待决名
- 函数 try 块
- 扩充命名空间 std
- 字母缩写
- RAII
- 三/五/零之法则
- PImpl
- 零开销原则
- 类型
- 隐式转换
- 注释
- C++ 关键词
- 预处理器
- C++ 标准库头文件
- 具名要求
- 功能特性测试 (C++20)
- 工具库
- 类型支持(基本类型、RTTI、类型特性)
- 概念库 (C++20)
- 错误处理
- 动态内存管理
- 日期和时间工具
- 字符串库
- 容器库
- 迭代器库
- 范围库 (C++20)
- 算法库
- 数值库
- 输入/输出库
- 文件系统库
- 本地化库
- 正则表达式库
- 原子操作库
- 线程支持库
- 实验性 C++ 特性
- 有用的资源
- 索引
- std 符号索引
- 协程支持 (C++20)
- C++ 关键词
类声明
类(class)与结构体(struct)是用户定义类型,以 类说明符 定义,它在声明语法的 声明说明符序列 中出现。类说明符拥有下列语法:
类关键词 attr 类头名 基类子句 { 成员说明 }
|
|||||||||
类关键词 | - | class 或 struct 之一。除了默认成员访问和默认基类访问之外,两个关键词是等同的。 |
attr(C++11) | - | 可选的任何数量属性序列,可包含 alignas 指定符 |
类头名 | - | 所定义的类的名字。可选地有限定,可选地后随关键词 final。名字可以省略,该情况下类是无名的(注意无名类不能为 final) |
基类子句 | - | 一或多个父类以及各自所用的继承模型的可选列表(见派生类) |
成员说明 | - | 访问说明符、成员对象及成员函数的声明和定义的列表(见下文) |
语法综述见类。若 类关键词 为 union
,则声明引入一个联合体类型。
前置声明
下列形式的声明
类关键词 attr 标识符 ;
|
|||||||||
声明一个将稍后在此作用域定义的类类型。直到定义出现前,此类名具有不完整类型。这允许类之间彼此引用:
class Vector; // 前置声明 class Matrix { // ... friend Vector operator*(const Matrix&, const Vector&); }; class Vector { // ... friend Vector operator*(const Matrix&, const Vector&); };
而且若特定的源文件仅使用到该类的指针和引用,这亦使得减少 #include 依赖成为可能:
// 在 MyStruct.h 中 #include <iosfwd> // 含有 std::ostream 的前置声明 struct MyStruct { int value; friend std::ostream& operator<<(std::ostream& os, const S& s); // 其定义在 MyStruct.cpp 文件中提供,该文件使用 #include <ostream> };
若前置声明出现于局部作用域,则它隐藏其外围作用域中可出现的先前声明的相同名字的类、变量、函数,以及所有其他声明:
struct s { int a; }; struct s; // 不做任何事(s 已定义于此作用域) void g() { struct s; // 新的局部类“s”的前置声明 // 它隐藏全局的 struct s 直至此块结尾 s* p; // 指向局部 struct s 的指针 struct s { char* p; }; // 局部 struct s 的定义 }
注意,通过作为其他声明一部分的详述类型说明符,也可以引入新的类名,但仅当名字查找无法找到先前声明的有此名的类时才行。
class U; namespace ns{ class Y f(class T p); // 声明函数 ns::f 并声明 ns::T 与 ns::Y class U f(); // U 指代 ::U Y* p; T* q; // 可使用到 T 和 Y 的指针及引用 }
成员说明
成员说明,或类定义的体,是花括号环绕的任何数量下列各项的序列:
1) 具有下列形式的成员声明
attr(可选) 声明说明符序列(可选) 成员声明符列表(可选) ;
|
|||||||||
attr(C++11) | - | 可选的任何数量属性序列 |
声明说明符序列 | - | 说明符的序列。它只在构造函数,析构函数,以及用户定义转换函数中可选。 |
成员声明符列表 | - | 与 初始化声明符列表相同,但额外允许位域定义、纯说明符和虚说明符( override 或 final ) (C++11 起),并且不允许直接非列表初始化语法。
|
这种声明可以声明静态及非静态的数据成员与成员函数、成员 typedef、成员枚举以及嵌套类。它亦可为友元声明。
class S { int d1; // 非静态数据成员 int a[10] = {1,2}; // 带初始化器的非静态数据成员 (C++11) static const int d2 = 1; // 带初始化器的静态数据成员 virtual void f1(int) = 0; // 纯虚成员函数 std::string d3, *d4, f2(int); // 两个数据成员和一个成员函数 enum {NORTH, SOUTH, EAST, WEST}; struct NestedS { std::string s; } d5, *d6; typedef NestedS value_type, *pointer_type; };
2) 函数定义,同时声明并定义成员函数或者友元函数。成员函数定义之后的分号是可选的。所有定义于类体之内的函数自动为内联的
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) {} // 构造函数定义 int operator()(size_t r, size_t c) const { // 成员函数定义 return data[r*C+c]; } int& operator()(size_t r, size_t c) { // 另一个成员函数定义 return data[r*C+c]; } };
3) 访问说明符
public:
、protected:
和 private:
class S { public: S(); // 公开构造函数 S(const S&); // 公开复制构造函数 virtual ~S(); // 公开虚析构函数 private: int* ptr; // 私有数据成员 };
4) using 声明
class Base { protected: int d; }; class Derived : public Base { public: using Base::d; // 令 Base 的受保护成员 d 为 Derived 的公开成员 using Base::Base; // 继承父类的全部构造函数 (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; }; };
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 起) |
局部类
类声明可出现于函数体内,该情况下它定义局部类。这种类的名字只存在于函数作用域中,且无法在函数外访问。
- 局部类不能拥有静态数据成员
- 局部类的成员函数无连接
- 局部类的成员函数必须完全在类体内定义
- 除闭包类型以外的 (C++14 起)局部类不能拥有成员模板
- 局部类不能拥有友元模板
- 局部类不能在类定义内定义友元函数
- 函数(包括成员函数)内的局部类可以访问其外围函数能访问的相同名字。
|
(C++11 前) |
运行此代码
#include <vector> #include <algorithm> #include <iostream> 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()); // C++11 起 for(int n: v) std::cout << n << ' '; }
输出:
3 2 1