名稱空間
變體
操作

類宣告

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 

類是使用者定義型別,由 class-specifier 定義,它出現在宣告語法的 decl-specifier-seq 中。

目錄

[編輯] 語法

類說明符具有以下語法:

class-key attr (可選) class-head-name class-property-specs (可選) base-clause (可選)
{ member-specification }
(1)
class-key attr (可選) base-clause (可選)
{ member-specification }
(2)
1) 命名類定義
2) 匿名類定義
類鍵 - 其中之一是 classstructunion。關鍵字 classstruct 除了預設成員訪問許可權和預設基類訪問許可權外是相同的。如果它是 union,則此宣告引入一個聯合型別
屬性 - (C++11 起) 任意數量的屬性,可以包含 alignas 說明符
class-head-name - 正在定義的類的名稱,可選地限定
class-property-specs - 以下說明符的列表,每個說明符在每個序列中最多允許出現一次。
說明符 效果
final
(C++11 起)
指定類不能被派生
trivially_relocatable_if_eligible     
(C++26 起)
如果符合條件,將類標記為可平凡重定位
replaceable_if_eligible     
(C++26 起)
如果符合條件,將類標記為可替換
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 (可選) ;
屬性 - (自 C++11 起) 任意數量的屬性
宣告說明符序列 - 說明符序列。它僅在建構函式、解構函式和使用者定義的型別轉換函式的宣告中可選。
member-declarator-list - 類似於init-declarator-list,但額外允許位域宣告純說明符,以及 virt-specifier(overridefinal(C++11 起),並且不允許直接非列表初始化語法

此宣告可以宣告靜態和非靜態資料成員成員函式、成員typedefs、成員列舉巢狀類。它也可以是友元宣告

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) using-宣告
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) using-enum-宣告
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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
CWG 1693 C++98 成員宣告不能為空 允許空宣告
CWG 1930 C++98 member-declarator-list 可能為空,當 decl-specifier-seq
包含儲存類說明符或 cv 限定符時
列表不能為空
CWG 2890 C++98 巢狀類成員可以在何處宣告尚不清楚 已明確

[編輯] 另請參閱

C 文件,關於 結構體宣告