Насколько я знаю, при определении функции с типом возвращаемого объекта, в то время как класс находится только в состоянии прямого объявления, например:
class A;
// переадресация объявления как неполный тип
A foo(){...}
// ошибка: A является неполным типом
Я знаю, что он прекрасно работает, когда он имеет возвращаемый тип указателя или ссылку на этот объект.
Но когда я определяю метод с типом возвращаемого значения в качестве его класса:
class B{
public:
B foo(){...}
}
Работает отлично.
Я думаю, что при определении метода в определении класса класс по-прежнему является неполным типом.
Поэтому я думаю, что это вызовет ошибку, похожую на предыдущую, но это не так.
Кто-нибудь знает почему?
Я долго искал, прежде чем просить о помощи здесь.
(Я плохо разбираюсь в английском, поэтому мое описание может вас запутать. Извините за это.)
В большинстве случаев вы правы, что не можете определить функцию, возвращающую неполный тип. Однако правила имеют некоторые исключения, позволяющие использовать класс в его собственном определении.
Можно объявить тип возврата B
для одной из его функций-членов, даже если B
является неполным в этой точке, как указано в C ++ 11 8.3.5 / 9:
Тип параметра или возвращаемого типа для определения функции не должен быть неполным типом класса (возможно, cv-квалифицированным) если только определение функции
вложен в член-спецификация для этого класса
Также хорошо создать экземпляр объекта типа B
вернуться в тело функции; в определении класса класс считается завершенным в различных контекстах, включая тела функций, как указано в C ++ 11 9.2 / 2:
В классе член-спецификация, класс считается завершенным в рамках функциональных органов, аргументы по умолчанию, исключение-технические характеристики, а также скобки или равно-инициализаторы для нестатических членов данных (включая такие вещи во вложенных классах). В противном случае он считается неполным в своем классе
член-спецификация.
При определении методов внутри класса класс обрабатывается так, как если бы он был полным типом, иначе мы не смогли бы определить встроенные методы. Кроме того, если бы ваш класс A был неполным типом, то любопытно повторяющийся шаблон не будет работать. Рассмотрим следующий код:
template <typename T> struct base {};
struct derived : base<derived> {}; // We can use derived here
// without any "incomplete type"// errors.
Другими словами: просто так работает язык.
РЕДАКТИРОВАТЬ: См. Ниже Mike Seymour для соответствующего раздела стандарта C ++, который упоминает это поведение.