12 Classes [class]

12.1 Class names [class.name]

Определение класса вводит новый тип. [Example:

struct X { int a; };
struct Y { int a; };
X a1;
Y a2;
int a3;

объявляет три переменные трех разных типов. Это означает, что

a1 = a2;                        // error: Y assigned to X
a1 = a3;                        // error: int assigned to X

несоответствия типов, и что

int f(X);
int f(Y);

объявить overloaded функцию, f() а не просто одну функцию f() дважды. По той же причине,

struct S { int a; };
struct S { int a; };            // error, double definition

неправильно сформирован, потому что он определяет S дважды. ]end example

Объявление класса вводит имя класса в область, в которой оно объявлено, и скрывает любой класс, переменную, функцию или другое объявление с этим именем во вложении scope. Если имя класса объявлено в области, где также объявлены переменная, функция или перечислитель с тем же именем, тогда, когда оба объявления находятся в области видимости, на класс можно ссылаться только с помощью elaborated-type-specifier([basic.lookup.elab]). [Example:

struct stat {
  // ...
};

stat gstat;                     // use plain stat to define variable

int stat(struct stat*);         // redeclare stat as function

void f() {
  struct stat* ps;              // struct prefix needed to name struct stat
  stat(ps);                     // call stat()
}

end example] A, состоящий исключительно из, является либо повторным объявлением имени в текущей области, либо прямым объявлением идентификатора как имени класса. Он вводит имя класса в текущую область видимости. [declarationclass-key identifier; Example:

struct s { int a; };

void g() {
  struct s;                     // hide global struct s with a block-scope declaration
  s* p;                         // refer to local struct s
  struct s { char* p; };        // define local struct s
  struct s;                     // redeclaration, has no effect
}

end example] [ Note: Такие объявления позволяют определять классы, которые ссылаются друг на друга. [Example:

class Vector;

class Matrix {
  // ...
  friend Vector operator*(const Matrix&, const Vector&);
};

class Vector {
  // ...
  friend Vector operator*(const Matrix&, const Vector&);
};

Объявление friends описано в [class.friend], операторные функции - в [over.oper]. ] ]end exampleend note

[ Note: An elaborated-type-specifierтакже может использоваться type-specifierкак часть объявления. Он отличается от объявления класса тем, что, если класс с подробным именем находится в области видимости, разработанное имя будет ссылаться на него. ] [end noteExample:

struct s { int a; };

void g(int s) {
  struct s* p = new struct s;   // global s
  p->a = s;                     // parameter s
}

end example]

[ Note: Объявление имени класса вступает в силу сразу после того, как identifierбудет замечено в определении класса или elaborated-type-specifier. Например,

class A * A;

first указывает, A что это имя класса, а затем переопределяет его как имя указателя на объект этого класса. Это означает, что class A для ссылки на класс необходимо использовать разработанную форму . Такой артистизм с именами может сбивать с толку, и его лучше избегать. ]end note

Имя typedef-nameтипа класса или его cv-квалифицированная версия также является class-name. Если a, typedef-nameкоторый именует тип класса cv-Qualified, используется там, где a class-nameтребуется, cv-квалификаторы игнорируются. А typedef-nameне должно использоваться как identifierв class-head.