Class declaration
클래스는 사용자 정의 타입으로, 클래스 지정자에 의해 정의되며 선언 구문의 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) | ||||||||
| class-key | - | 다음 중 하나: class , struct , union . class 와 struct 키워드는 기본 멤버 접근 제어 와 기본 기본 클래스 접근 제어 를 제외하고 동일합니다. union 인 경우, 선언은 공용체 타입 을 도입합니다. | ||||||||
| attr | - |
(C++11부터)
임의의 수의
속성들
,
alignas
지정자를 포함할 수 있음
|
||||||||
| class-head-name | - | 정의 중인 클래스의 이름, 선택적으로 한정됨 | ||||||||
| class-property-specs | - |
다음 지정자들의 목록, 각 지정자는 각 시퀀스에서 최대 한 번만 허용됨.
|
||||||||
| base-clause | - | 하나 이상의 기본 클래스들과 각각에 사용된 상속 모델의 목록 ( 파생 클래스 참조) | ||||||||
| member-specification | - | 접근 지정자, 멤버 객체 및 멤버 함수 선언과 정의의 목록 ( 아래 참조 ) |
전방 선언
다음과 같은 형태의 선언
class-key
attr
identifier
;
|
|||||||||
이 스코프 내에서 나중에 정의될 클래스 타입을 선언합니다. 정의가 나타나기 전까지 이 클래스 이름은 incomplete type 을 가집니다. 이를 통해 서로를 참조하는 클래스들이 가능해집니다:
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); // 정의는 #include <ostream>을 사용하는 MyStruct.cpp 파일에서 제공됨 };
전방 선언이 지역 범위에 나타나면, 이는 가립니다 이전에 선언된 클래스, 변수, 함수 및 바깥쪽 범위에 나타날 수 있는 동일한 이름의 모든 다른 선언들을:
struct s { int a; }; struct s; // 아무 동작도 하지 않음 (s는 이미 이 스코프에서 정의됨) void g() { struct s; // 새로운 지역 struct "s"의 전방 선언 // 이는 이 블록의 끝까지 전역 struct s를 가림 s* p; // 지역 struct s를 가리키는 포인터 struct s { char* p; }; // 지역 struct s의 정의 }
새로운 클래스 이름은 다른 선언의 일부로 나타나는 elaborated type specifier 에 의해 도입될 수도 있지만, 이는 name lookup 가 동일한 이름을 가진 이전에 선언된 클래스를 찾을 수 없는 경우에만 해당합니다.
class U; namespace ns { class Y f(class T p); // ns::f 함수를 선언하고 ns::T와 ns::Y를 선언합니다 class U f(); // U는 ::U를 참조합니다 // T와 Y에 대한 포인터와 참조를 사용할 수 있습니다 Y* p; T* q; }
멤버 명세
멤버 명세, 또는 클래스 정의의 본문 은 다음 중 임의의 개수로 구성된 중괄호로 둘러싸인 시퀀스입니다:
attr
(optional)
decl-specifier-seq
(optional)
member-declarator-list
(optional)
;
|
|||||||||
| attr | - | (since C++11) 임의의 개수의 attributes |
| decl-specifier-seq | - | specifiers 의 시퀀스. 생성자, 소멸자, 사용자 정의 타입 conversion functions 선언에서만 선택적임 |
| member-declarator-list | - |
init-declarator-list
와 유사하지만, 추가적으로
bit-field declaration
,
pure-specifier
, 및 virt-specifier (
override
또는
final
)
(since C++11)
를 허용하고,
direct-non-list-initialization syntax
는 허용하지 않음
|
이 선언은 static 및 비정적 data members 와 member functions , 멤버 typedefs , 멤버 enumerations , 및 nested classes 를 선언할 수 있습니다. 또한 friend declaration 일 수도 있습니다.
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; };
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]; } };
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 };
class Base { protected: int d; }; class Derived : public Base { public: using Base::d; // Base의 protected 멤버 d를 Derived의 public 멤버로 만듦 using Base::Base; // 모든 기본 클래스의 생성자 상속 (C++11) };
static_assert
선언:
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point"); };
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
| (C++11부터) |
|
8)
deduction guides
of member class templates:
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++20부터) |
지역 클래스
함수 본문 내부에 클래스 선언이 나타날 수 있으며, 이 경우 지역 클래스(local class) 를 정의합니다. 이러한 클래스의 이름은 함수 범위 내에서만 존재하며 외부에서는 접근할 수 없습니다.
- 로컬 클래스의 멤버는 해당 클래스의 정의 내에서만 선언될 수 있으나, 중첩 클래스 인 멤버는 해당 클래스의 가장 가까운 블록 스코프 에서도 선언될 수 있습니다.
- 로컬 클래스 내에 중첩된 클래스 또한 로컬 클래스입니다.
- 로컬 클래스는 정적 데이터 멤버를 가질 수 없습니다.
- 로컬 클래스의 멤버 함수는 링크age를 가지지 않습니다.
- 로컬 클래스의 멤버 함수는 클래스 본문 내에서 완전히 정의되어야 합니다.
- 로컬 클래스는 클로저 타입 이 아닌 경우 (C++14부터) 멤버 템플릿을 가질 수 없습니다.
- 로컬 클래스는 프렌드 템플릿 을 가질 수 없습니다.
- 로컬 클래스는 클래스 정의 내부에 프렌드 함수 를 정의할 수 없습니다.
- 함수(멤버 함수 포함) 내부의 로컬 클래스는 외부 함수가 접근할 수 있는 이름들과 동일한 이름들에 접근할 수 있습니다.
|
(until 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
키워드
결함 보고서
다음 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 1693 | C++98 | 멤버 선언이 비어 있을 수 없었음 | 빈 선언 허용됨 |
| CWG 1930 | C++98 |
member-declarator-list
가
decl-specifier-seq
에 저장 클래스 지정자나 cv 한정자가 포함될 때 비어 있을 수 있었음 |
리스트는 비어 있으면 안 됨 |
| CWG 2890 | C++98 | 중첩 클래스의 멤버 선언 위치가 불명확했음 | 명확하게 규정됨 |
참고 항목
|
C 문서
에 대한
구조체 선언
|