별칭 및 typedef(C++)
별칭 선언을 사용하여 이전에 선언된 형식의 동의어로 사용할 이름을 선언할 수 있습니다. (이 메커니즘은 비공식적으로 형식 별칭이라고 도 함). 이 메커니즘을 사용하여 사용자 지정 할당자에 유용할 수 있는 별칭 템플릿을 만들 수도 있습니다.
구문
using identifier = type;
설명
identifier
별칭 이름입니다.
type
별칭을 만드는 형식 식별자입니다.
별칭은 새 형식을 도입하지 않으며 기존 형식 이름의 의미를 변경할 수 없습니다.
가장 간단한 형태의 별칭은 C++03의 typedef
메커니즘과 동일합니다.
// 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
Typedef
선언은 typedef
해당 범위 내에서 선언의 형식 선언 부분에서 지정된 형식의 동의어가 되는 이름을 소개합니다.
typedef 선언을 사용하여 언어로 이미 정의된 형식 또는 선언한 형식에 대해 더 짧거나 더 의미 있는 이름을 생성할 수 있습니다. typedef 이름을 사용하면 변경될 수 있는 구현 정보를 캡슐화할 수 있습니다.
선언은 class
, struct
, union
및 선언 typedef
과 enum
달리 새 형식을 도입하지 않으며 기존 형식에 대한 새 이름을 도입합니다.
선언 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;
다음 예제에서는 값을 반환하지 않고 두 개의 int 인수를 사용하는 함수에 대한 DRAWF
형식을 제공합니다.
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
는 두 개의 헤더 파일이 포함되며, 둘 다 이름CHAR
에 대한 선언을 포함합니다typedef
. 두 선언이 동일한 형식을 참조하는 한 이러한 재선언은 허용됩니다.
A typedef
는 이전에 다른 형식으로 선언된 이름을 다시 정의할 수 없습니다. 이 대안은 다음과 같습니다.file2.h
// file2.h
typedef int CHAR; // Error
컴파일러는 다른 형식을 참조하기 위해 이름을 CHAR
다시 묶으려고 했기 때문에 오류를 prog.cpp
발생합니다. 이 정책은 다음과 같은 구문으로 확장됩니다.
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의 typedef
선언에서 typedef
명명되지 않은 구조를 typedef
선언하는 ANSI C 사례로 인해 클래스 형식과 함께 지정자의 사용이 주로 지원됩니다. 예를 들어 많은 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++에서는 이름과 실제 형식(, , struct
union
및 enum
키워드(keyword)으로 선언됨class
)의 차이가 typedef
더 뚜렷합니다. 문에서 typedef
이름 없는 구조를 선언하는 C 사례는 여전히 작동하지만 C에서와 마찬가지로 표기법상의 이점을 제공하지 않습니다.
// typedef_with_class_types2.cpp
// compile with: /c /W1
typedef struct {
int POINT();
unsigned x;
unsigned y;
} POINT;
앞의 예제에서는 명명되지 않은 클래스 구문을 사용하여 명명 POINT
된 클래스 typedef
를 선언합니다. POINT
는 클래스 이름으로 간주되지만 다음과 같은 제한 사항이 이런 방식으로 생성된 이름에 적용됩니다.
이름(동의어)은 ,
struct
또는union
접두사 뒤를class
표시할 수 없습니다.이 이름은 클래스 선언 내에서 생성자 또는 소멸자 이름으로 사용할 수 없습니다.
요약하자면, 이 구문은 상속, 생성 또는 소멸을 위한 메커니즘을 제공하지 않습니다.
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기