Как отвечал ранее Earwicker, вы не можете использовать предварительные объявления ни в одном из этих случаев, так как компилятору необходимо знать размер класса.
Вы можете использовать только предварительное объявление в наборе операций:
- объявление функций, которые принимают объявленный вперед класс в качестве параметров или возвращают его
- объявление указателей членов или ссылок на объявленный вперед класс
- объявление статических переменных типа, объявленного вперед, в определении класса
Вы не можете использовать его для
- объявляет атрибут члена данного типа (компилятору требуется размер)
- определить или создать объект типа или удалить его
- вызов любого статического или метода-члена класса или доступ к любому члену или статическому атрибуту
(я что-нибудь забыл?)
Примите во внимание, что объявление auto_ptr
не то же самое, что объявление необработанного указателя, так как экземпляр auto_ptr
попытается удалить указатель, когда он выходит из области видимости, и удаление требует полного объявления типа. Если вы используете auto_ptr
in для хранения объявленного типа вперед, вам придется предоставить деструктор (даже если он пуст) и определить его после того, как будет объявлено полное объявление класса.
Есть также некоторые другие тонкости. Когда вы объявляете класс вперед, вы сообщаете компилятору, что это будет класс. Это означает, что он не может быть enum
или typedef
другого типа. Это проблема, с которой вы сталкиваетесь, когда пытаетесь переадресовать объявление std::string
, так как это typedef определенного экземпляра шаблона:
typedef basic_string<char> string; // aproximate
Чтобы переслать объявление строки, вам нужно переслать объявление шаблона basic_string
, а затем создать typedef
. Проблема в том, что стандарт не устанавливает количество параметров, которые принимает шаблон basic_string
, он просто утверждает, что если он принимает более одного параметра, остальные параметры должны иметь тип по умолчанию, чтобы приведенное выше выражение компилировалось. Это означает, что не существует стандартного способа объявить шаблон вперед.
Если, с другой стороны, вы хотите заранее объявить нестандартный шаблон (т.е. не STL), вы можете делать это до тех пор, пока вы знаете число параметров:
template <typename T, typename U> class Test; // correct
//template <typename T> class Test; // incorrect even if U has a default type
template <typename T, typename U = int> class Test {
// ...
};
В конце совет, который дал вам Родди: вперед, объявите столько, сколько сможете, но примите, что некоторые вещи должны быть включены.