类声明

来自cppreference.com
< cpp‎ | language

class 与 struct 是用户定义类型,以 class-specifier 定义,它出现于声明语法的 decl-specifier-seq 中。类指定符拥有下列语法:

class-key attr class-head-name base-clause { member-specification }
class-key - classstruct 之一。关键词是等同的,除了默认成员访问和默认基类访问
attr(C++11) - 可选的任何数量属性序列,可包含 alignas 指定符
class-head-name - 将被定义的类的名称。可选地为限定,可选地后随关键词 final 。名称可以省略,该情况下类是无名的(注意无名类不能为 final
base-clause - 一或多个亲类及用于每一者的继承模式的可选列表(见 派生类
member-specification - 访问指定符、成员对象及成员函数声明与定义的列表(见后述)

语法综述见。若 class-keyunion ,则声明引入一个联合体类型

目录

[编辑] 前置声明

下列形式的声明

class-key attr identifier ;

声明一个将要在此作用域后方定义的类类型。在定义出现前,此类名拥有不完整类型。这允许类彼此引用:

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(可选) decl-specifier-seq(可选) member-declarator-list(可选) ;
attr(C++11) - 可选的任何数量属性序列
decl-specifier-seq - 指定符序列。它只在构造函数、析构函数,及用户定义转换函数中可选。
member-declarator-list - init-declarator-list ,但额外允许位域定义纯指定符及虚指定符( overridefinal (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) 函数定义,可以声明并定义成员函数友元函数。成员函数定义后的分号是可选的。所有定义于类体内的函数是自动 inline
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();          // public 构造函数
    S(const S&);  // public 复制构造函数
    virtual ~S(); // public 虚析构函数
 private:
    int* ptr; // private 数据成员
};
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;
    };
};
7) 别名声明
template <typename T>
struct identity
{
    using type = T;
};
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

[编辑] 参阅

结构体声明C 文档