共用方式為


別名和 typedef (C++)

您可以使用 別名宣告 來宣告名稱,以做為先前宣告類型的同義字。 (這種機制也稱為 類型別名)。 您也可以使用此機制來建立 別名範本,這對於自訂配置器很有用。

語法

using identifier = type;

備註

識別碼
別名的名稱。

type
您要為其建立別名的類型識別碼。

別名不會引進新的類型,而且無法變更現有類型名稱的意義。

別名的最簡單形式相當於 typedef 來自 C++03 的機制:

// C++11
using counter = long;

// C++03 equivalent:
// typedef long counter;

這兩種形式都可讓您建立 類型的 counter變數。 更有用的是像 std::ios_base::fmtflags 的這個類類型名:

// C++11
using fmtfl = std::ios_base::fmtflags;

// C++03 equivalent:
// typedef std::ios_base::fmtflags fmtfl;

fmtfl fl_orig = std::cout.flags();
fmtfl fl_hex = (fl_orig & ~std::cout.basefield) | std::cout.showbase | std::cout.hex;
// ...
std::cout.flags(fl_hex);

別名也適用於函式指標,但比對等的 typedef 更容易閱讀:

// C++11
using func = void(*)(int);

// C++03 equivalent:
// typedef void (*func)(int);

// func can be assigned to a function pointer value
void actual_function(int arg) { /* some code */ }
func fptr = &actual_function;

機制的限制 typedef 是它不適用於範本。 不過,C++11 的類類型名語法啟用別名樣板的建立:

template<typename T> using ptr = T*;

// the name 'ptr<T>' is now an alias for pointer to T
ptr<int> ptr_int;

範例

下列範例示範如何搭配使用別名樣板與自訂配置器 (在這個案例中為整數向量類型)。 您可以替代任何類型 int ,以建立方便的別名,以隱藏主要功能程式代碼中的複雜參數清單。 透過在整個程式代碼中使用自定義配置器,您可以改善可讀性,並降低引入錯字所造成的錯誤的風險。

#include <stdlib.h>
#include <new>

template <typename T> struct MyAlloc {
    typedef T value_type;

    MyAlloc() { }
    template <typename U> MyAlloc(const MyAlloc<U>&) { }

    bool operator==(const MyAlloc&) const { return true; }
    bool operator!=(const MyAlloc&) const { return false; }

    T * allocate(const size_t n) const {
        if (n == 0) {
            return nullptr;
        }

        if (n > static_cast<size_t>(-1) / sizeof(T)) {
            throw std::bad_array_new_length();
        }

        void * const pv = malloc(n * sizeof(T));

        if (!pv) {
            throw std::bad_alloc();
        }

        return static_cast<T *>(pv);
    }

    void deallocate(T * const p, size_t) const {
        free(p);
    }
};

#include <vector>
using MyIntVector = std::vector<int, MyAlloc<int>>;

#include <iostream>

int main ()
{
    MyIntVector foov = { 1701, 1764, 1664 };

    for (auto a: foov) std::cout << a << " ";
    std::cout << "\n";

    return 0;
}
1701 1764 1664

Typedefs

typedef宣告引進名稱,其範圍內會成為宣告類型宣告部分所指定類型的同義字。

您可以使用 typedef 宣告,針對語言或已宣告的類型,建構更簡短或更有意義的名稱。 Typedef 名稱可讓您封裝可能變更的實作詳細資料。

與 、 classstructunion 宣告相反enumtypedef宣告不會引進新的類型; 它們會為現有類型引進新的名稱。

使用 typedef 宣告的名稱會佔用與其他標識符相同的命名空間(語句標籤除外)。 因此,除了類別類型宣告之外,它們不能使用與先前宣告之名稱相同的標識碼。 請考慮下列範例:

// typedef_names1.cpp
// C2377 expected
typedef unsigned long UL;   // Declare a typedef name, UL.
int UL;                     // C2377: redefined.

與其他標識碼相關的名稱隱藏規則也會控管使用 typedef宣告的名稱可見度。 因此,下列範例在 C++ 中是合法的:

// typedef_names2.cpp
typedef unsigned long UL;   // Declare a typedef name, UL
int main()
{
   unsigned int UL;   // Redeclaration hides typedef name
}

// typedef UL back in scope

另一個名稱實例隱藏:

// typedef_specifier1.cpp
typedef char FlagType;

int main()
{
}

void myproc( int )
{
    int FlagType;
}

當您以與 typedef相同的名稱宣告區域範圍標識符時,或當您在相同範圍或內部範圍中宣告結構或等位的成員時,必須指定類型規範。 例如:

typedef char FlagType;
const FlagType x;

若要重複使用 FlagType 名稱做為識別項、結構成員或等位成員的名稱,必須提供類型:

const int FlagType;  // Type specifier required

只有下列做法是不夠的:

const FlagType;      // Incomplete specification

FlagType因為會被視為型別的一部分,而不是要重新宣告的標識符。 此宣告會採用為不合法的宣告,類似於:

int;  // Illegal declaration

您可以使用 typedef 宣告任何類型,包括指標、函式和陣列類型。 您可以在定義結構或等位類型之前宣告結構或等位類型指標的 typedef 名稱,只要定義的可見度和宣告相同即可。

範例

宣告的 typedef 其中一個用法是讓宣告更加統一且精簡。 例如:

typedef char CHAR;          // Character type.
typedef CHAR * PSTR;        // Pointer to a string (char *).
PSTR strchr( PSTR source, CHAR target );
typedef unsigned long ulong;
ulong ul;     // Equivalent to "unsigned long ul;"

若要在 typedef 相同的宣告中指定基本和衍生型別,您可以使用逗號分隔宣告子。 例如:

typedef char CHAR, *PSTR;

下列範例提供類型 DRAWF 給未傳回任何值的函式,並且接受兩個 int 引數:

typedef void DRAWF( int, int );

在上述 typedef 語句之後,宣告

DRAWF box;

相當於下列宣告:

void box( int, int );

typedef 通常會結合 struct 來宣告和命名使用者定義型別:

// typedef_specifier2.cpp
#include <stdio.h>

typedef struct mystructtag
{
    int   i;
    double f;
} mystruct;

int main()
{
    mystruct ms;
    ms.i = 10;
    ms.f = 0.99;
    printf_s("%d   %f\n", ms.i, ms.f);
}
10   0.990000

重新宣告 typedefs

宣告 typedef 可用來重新宣告相同名稱,以參考相同的類型。 例如:

來源檔案 file1.h

// file1.h
typedef char CHAR;

來源檔案 file2.h

// file2.h
typedef char CHAR;

來源檔案 prog.cpp

// prog.cpp
#include "file1.h"
#include "file2.h"   // OK

檔案 prog.cpp 包含兩個頭檔,兩者都包含 typedef 名稱 CHAR的宣告。 只要兩個宣告都參考相同的類型,就可以接受此類重新宣告。

typedef無法重新定義先前宣告為不同類型的名稱。 請考慮此替代方法 file2.h

// file2.h
typedef int CHAR;     // Error

編譯程式會在 中 prog.cpp 發出錯誤,因為嘗試重新宣告名稱 CHAR 以參考不同的類型。 此原則延伸至建構,例如:

typedef char CHAR;
typedef CHAR CHAR;      // OK: redeclared as same type

typedef union REGS      // OK: name REGS redeclared
{                       //  by typedef name with the
    struct wordregs x;  //  same meaning.
    struct byteregs h;
} REGS;

C++與 C 中的 typedefs

typedef由於 ANSI C 在宣告中typedef宣告未命名結構的做法,因此支援搭配類別類型使用規範。 例如,許多 C 程式設計人員會使用下列成語:

// typedef_with_class_types1.cpp
// compile with: /c
typedef struct {   // Declare an unnamed structure and give it the
                   // typedef name POINT.
   unsigned x;
   unsigned y;
} POINT;

這類宣告的優點是可以執行類似以下的宣告:

POINT ptOrigin;

而非:

struct point_t ptOrigin;

在C++中,typedef名稱與實數類型之間的差異(以 classstructunion、 和 enum 關鍵詞宣告)比較明顯。 雖然在語句中 typedef 宣告無名稱結構的 C 做法仍然有效,但它在 C 中不會提供表示法優點。

// typedef_with_class_types2.cpp
// compile with: /c /W1
typedef struct {
   int POINT();
   unsigned x;
   unsigned y;
} POINT;

上述範例會使用未命名的類別語法宣告名為 POINT 的類別 typedefPOINT 是類別名稱;不過,以此方式產生的名稱會受到下列限制:

  • 名稱 (同義字) 不能出現在、 classstruct 前置詞之後union

  • 名稱不能當做類別宣告內的建構函式或解構函式名稱使用。

總而言之,此語法不會提供繼承、建構或解構的任何機制。