﻿# Неполный тип

Неполный тип – это элемент, который сообщает компилятору, что существует тип с таким именем, но ничего не говорит ему о том, как он реализован: какие есть функции, переменные и т\. д\. Обычно эти типы полностью определяются позже, поэтому такое объявление часто называют опережающим \(forward declaration\)\.

К неполным типам относятся:

* тип void;
* структуры, классы, объединения, для которых ещё не определена реализация;
* массивы неопределённого размера;
* массивы элементов неполного типа\.

Чтобы тип стал полным \(полностью определенным\) необходимо указать недостающую информацию\. Отдельно стоит отметить тип void, который не может быть полным в принципе\. 

## Ограничения при использовании неполных типов

Так как неполный тип ничего не говорит компилятору о своём внутреннем устройстве, то не получится скомпилировать код, который пытается получить доступ к его содержимому\. Также невозможно будет выполнить операции, требующие знания точного размера типа\. Для этого необходимо знать размер типов, которые содержатся в требуемом классе\.

## Примеры неполных типов и способы их полного определения

Неполный тип можно получить при использовании следующих конструкций языка:

**Опережающая декларация \(forward\-declaration\):**

```cpp
class MyType;
```

**Указатель на неизвестный тип:**

```cpp
struct MyType *myPtr;
```

**Массив, содержащий элементы неопределённого типа \(даже если количество элементов известно\):**

```cpp
MyType b[10];
```

Во всех этих случаях, для полного определения типа, мы обязаны предоставить где\-нибудь реализацию типа 'MyType'\. Например, такую:

```cpp
class MyType {
  int someNumber;
}
```

В таком случае все ограничения, накладываемые на неполные типы, будут сняты\.

Отдельного разъяснения заслуживает ситуация с массивами неопределённого размера, т\. к\. при их использовании есть несколько нюансов\. Например:

```cpp
extern int a[];        // Неполный тип (массив неизвестного 
   // размера с элементами типа 'int')
int b[] = { 1, 2, 3 }; // Полный тип (массив из трёх значений типа 'int')
int c[10];             // Полный тип
```

Также на массивы неизвестного размера могут быть созданы ссылки и указатели, но в языке С\+\+ они не могут быть инициализированы \(или присвоены\) указателями на массивы с известным размером\. Данное ограничение отсутствует в языке С, т\. к\. там указатели на обычные массивы и на массивы неизвестного размера совместимы, а поэтому могут свободно конвертироваться и присваиваться в обоих направлениях\.

```cpp
extern int a[];
int (&a1)[]  = a;    // ОК
int (*a2)[]  = &a;   // ОК
int (*a3)[2] = &a;   // Ошибка в С++, но корректно в С
 
int b[] = {1, 2, 3};
int (&b1)[] = b;     // Ошибка
int (*b2)[] = &b;    // Ошибка в С++, но корректно в С
```