Зачем это делать?
Поскольку компилятор знает только имена, которые были объявлены.Поэтому, если вы хотите использовать класс, вы должны объявить его.Но если его определение зависит от пользователя, может потребоваться предварительное объявление, если пользователь, в свою очередь, зависит не от определения класса, а только от его объявления (= name).
В частности, еслипользователю просто нужен указатель или ссылка, это не зависит от определения.Но в перечисленных случаях (которые не претендуют на исключительность, поскольку это стандартная ненормативная выдержка), пользователь зависит от определения класса T, если
- определен объект типа T(3.1), либо
- T используется в качестве типа объекта или типа элемента массива в выражении new (5.3.4), либо
- применяется преобразование lvalue-в-значениеЗначение l, относящееся к объекту типа T (4.1) или
- , выражение преобразуется (неявно или явно) в тип T (п. 4, 5.2.3, 5.2.7, 5.2.9, 5.4) или
- выражение, которое не является константой нулевого указателя и имеет тип, отличный от void *, преобразуется в указатель типа на T или ссылку на T с использованием неявного преобразования (раздел 4), dynamic_cast(5.2.7) или static_cast (5.2.9), или
- оператор доступа к члену класса применяется к выражению типа T (5.2.5), или
- оператор typeid(5.2.8) или оператор sizeof (5.3.3) применяется к операнду типа T или
- функция с типом возвращаемого значения или типом аргумента типа T определяется (3.1) или вызывается (5.2.2), или
- определяется класс с базовым классом типа T (раздел 10),или
- значение l типа T присваивается (5.17), или
- объявление исключения имеет тип T, ссылку на T или указатель на T (15.3).
В этих случаях предварительное объявление будет не достаточным, и вам необходимо полностью его определить.
Это нужно?
Да, в случаях, когда это необходимо, это необходимо.В следующем случае это так, потому что оба класса ссылаются друг на друга.
class A;
class B {
// forward declaration needed
void f(A);
};
class A {
void f(B);
};
// "- a function with a return type or argument type of type T is defined"
void B::f(A) {
}
Для определения функции-члена требуется не только объявление, но и определение класса A.
Каковы преимущества?Недостатки?
Преимущества в том, что ваша программа компилируется.Недостатком является то, что вы загрязнили прицел еще одним именем.Но это неизбежное зло этого.