Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Deklaraci aliasu můžete použít k deklarování názvu, který se má použít jako synonymum pro dříve deklarovaný typ. (Tento mechanismus se také označuje jako neformálně jako alias typu). Pomocí tohoto mechanismu můžete také vytvořit šablonu aliasu, která může být užitečná pro vlastní alokátory.
Syntaxe
using identifier = type;
Poznámky
identifikátor
Název aliasu.
type
Identifikátor typu, pro který vytváříte alias.
Alias nezavádí nový typ a nemůže změnit význam existujícího názvu typu.
Nejjednodušší forma aliasu je ekvivalentem typedef
mechanismu z C++03:
// C++11
using counter = long;
// C++03 equivalent:
// typedef long counter;
Oba tyto formuláře umožňují vytváření proměnných typu counter
. Něco užitečnějšího by byl alias typu podobný tomuto: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);
Aliasy také fungují s ukazateli funkcí, ale jsou mnohem čitelnější než ekvivalentní definice 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;
Omezení typedef
mechanismu spočívá v tom, že nefunguje se šablonami. Syntaxe aliasu typu v jazyce C++11 však umožňuje vytváření šablon aliasů:
template<typename T> using ptr = T*;
// the name 'ptr<T>' is now an alias for pointer to T
ptr<int> ptr_int;
Příklad
Následující příklad ukazuje použití šablony aliasu s vlastním alokátorem – v tomto případě typu celočíselného vektoru. Pokud chcete vytvořit pohodlný alias pro skrytí složitých seznamů parametrů v hlavním funkčním kódu, můžete nahradit libovolný typ int
. Pomocí vlastního alokátoru v celém kódu můžete zlepšit čitelnost a snížit riziko zavedení chyb způsobených překlepy.
#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
Deklarace typedef
zavádí název, který se v rámci jeho oboru stane synonymem pro typ zadaný částí deklarace typu deklarace.
Deklarace typedef můžete použít k vytvoření kratších nebo smysluplnějších názvů pro typy, které jsou již definovány jazykem nebo pro typy, které jste deklarovali. Názvy typedef umožňují zapouzdřit podrobnosti implementace, které se mohou změnit.
Na rozdíl od class
deklarací , , struct
union
a enum
deklarací typedef
deklarace nezavádějí nové typy; zavádějí nové názvy pro existující typy.
Názvy deklarované pomocí typedef
zabírají stejný obor názvů jako ostatní identifikátory (kromě popisků příkazů). Proto nemohou použít stejný identifikátor jako dříve deklarovaný název, s výjimkou deklarace typu třídy. Představte si následující příklad:
// typedef_names1.cpp
// C2377 expected
typedef unsigned long UL; // Declare a typedef name, UL.
int UL; // C2377: redefined.
Pravidla skrývání názvů, která se týkají jiných identifikátorů, také řídí viditelnost názvů deklarovaných pomocí typedef
. Následující příklad je proto v jazyce C++ platný:
// 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
Další instance skrytí názvu:
// typedef_specifier1.cpp
typedef char FlagType;
int main()
{
}
void myproc( int )
{
int FlagType;
}
Když deklarujete identifikátor místního oboru stejným názvem jako nebo typedef
když deklarujete člen struktury nebo sjednocení ve stejném oboru nebo ve vnitřním oboru, musí být specifikátor typu zadán. Příklad:
typedef char FlagType;
const FlagType x;
Pro opětovné použití názvu FlagType
pro identifikátor, člen struktury nebo člen sjednocení musí být určen typ:
const int FlagType; // Type specifier required
Není to dostatečné k tomu, abyste řekli
const FlagType; // Incomplete specification
FlagType
protože se považuje za součást typu, nikoli identifikátor, který je předefinován. Toto prohlášení se považuje za nezákonné prohlášení, podobně jako:
int; // Illegal declaration
Můžete deklarovat libovolný typ, typedef
včetně ukazatele, funkce a typů polí. Je možné deklarovat název typedef pro ukazatel na typ struktury nebo sjednocení před definováním typu struktury nebo sjednocení, pokud má definice stejnou viditelnost jako deklarace.
Příklady
Jedním z použití typedef
deklarací je, aby deklarace byly jednotnější a kompaktnější. Příklad:
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
Chcete-li určit základní a odvozené typy ve stejné deklaraci, můžete deklarátory oddělit čárkami. Příklad:
typedef char CHAR, *PSTR;
Následující příklad poskytuje typ DRAWF
pro funkci nevracející žádnou hodnotu a přijímající dva celočíselné argumenty:
typedef void DRAWF( int, int );
Za výše uvedeným typedef
příkazem deklarace
DRAWF box;
ekvivalentní deklaraci
void box( int, int );
typedef
často se kombinuje s struct
deklarovat a pojmenovat uživatelem definované typy:
// 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
Redeclaration of typedefs
Deklarace typedef
se dá použít k opětovnému pojmenování stejného názvu, aby odkazovat na stejný typ. Příklad:
Zdrojový soubor file1.h
:
// file1.h
typedef char CHAR;
Zdrojový soubor file2.h
:
// file2.h
typedef char CHAR;
Zdrojový soubor prog.cpp
:
// prog.cpp
#include "file1.h"
#include "file2.h" // OK
Soubor prog.cpp
obsahuje dva soubory hlaviček, z nichž oba obsahují typedef
deklarace pro název CHAR
. Pokud obě tyto deklarace odkazují na stejný typ, je taková změna deklarace přijatelná.
Nelze typedef
předefinovat název, který byl dříve deklarován jako jiný typ. Zvažte tuto alternativu file2.h
:
// file2.h
typedef int CHAR; // Error
Kompilátor vydá chybu prog.cpp
kvůli pokusu o opětovné pojmenování názvu CHAR
, aby odkazoval na jiný typ. Tato zásada se vztahuje na konstrukce, jako jsou:
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;
typedefs v C++ vs. C
Použití specifikátoru typedef
s typy tříd je podporováno z velké části z důvodu praxe ANSI C deklarování nepojmenovaných struktur v typedef
deklaracích. Například mnoho programátorů jazyka C používá následující idiom:
// 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;
Výhodou takovéto deklarace je, že umožňuje deklarace, jako jsou:
POINT ptOrigin;
místo:
struct point_t ptOrigin;
V jazyce C++ je rozdíl mezi typedef
názvy a skutečnými typy (deklarován pomocí class
, struct
union
, a enum
klíčových slov) odlišnější. I když c postup deklarování beznázvové struktury v typedef
příkazu stále funguje, neposkytuje žádné notační výhody, jak to dělá v jazyce C.
// typedef_with_class_types2.cpp
// compile with: /c /W1
typedef struct {
int POINT();
unsigned x;
unsigned y;
} POINT;
Předchozí příklad deklaruje třídu pojmenovanou POINT
pomocí syntaxe nepojmenované třídy typedef
. POINT
je považován za název třídy; Následující omezení se však vztahují na názvy zavedené tímto způsobem:
Název (synonymum) se nemůže zobrazit za symbolem ,
struct
nebounion
předponouclass
.Název nelze použít jako konstruktor nebo název destruktoru v rámci deklarace třídy.
V souhrnu tato syntaxe neposkytuje žádný mechanismus dědičnosti, konstrukce nebo zničení.