прямое объявление генерирует несовместимую ошибку типа

Я читал некоторые о предварительных декларациях, в том числе на этом форуме. Все они говорят, что это спасает нас от включения файла заголовка, однако следующий код генерирует ошибку:

#ifndef CLASSA_H_
#define CLASSA_H_

class B;

class A {

public:
    A();
    ~A();
    int getCount();
private:
    static int _count;
    int _num;
    B _b1;   //ERROR

};

Компилятор говорит:A.h:23: error: field ‘_b1’ has incomplete type

Я заметил, что если я сделаю_b1 типаB* проблема решена.

Так является ли прямое объявление хорошим только для типов указателей?
Если я хочуA держатьB возражать, я должен#inlcude "B.h" ?

Спасибо!

 Luc Touraille29 сент. 2010 г., 19:02
Немного саморекламы: вот ответ, который объясняетчто вы можете и не можете делать с неполными типами (то есть типы, которые объявлены, но еще не определены).

Ответы на вопрос(4)

Решение Вопроса

B определить хотя бы какой размер отдать классуA, Если вы используете указатель, он знает его размер.

Обратите внимание, что циклические зависимости невозможны. Если ты хочешь

class A { B b; };
class B { A a; };

тогда A и B должны иметь бесконечный размер ...

 Aaron Anodide29 сент. 2010 г., 18:12
+1 я поражен, я не знал этого

предварительные объявления работают, только если вы используете указатели и ссылки на объявленный вперед тип. Если вы используете объект по значению, вам нужно включить полный заголовочный файл.

 sbi29 сент. 2010 г., 18:17
Хорошо, предварительные объявления будут работать для использования в качестве функции типадекларации, тоже:B f(B); Вам нужно полное определениеB на самом делеопределять эта функция, хотя.

заранее объявленный тип в

использовать указатели и ссылки на него в качестве членов данныхиспользовать его в качестве аргумента (даже принимая для каждой копии) или возвращаемого типа (даже возвращая для каждой копии) для функциидекларации.

Тебе понадобитсяполное определение типа чтобы

использовать его как член класса данныхиспользовать его в функцииопределения.

Если вы помните, что форвард-декларация на самом деле невернадекларация (другого пути нетдекларирование тип класса, таклюбая декларация типа класса является предварительным объявлением), и что всякий раз, когда вы открываете фигурные скобки послеclass/struct/union плюс идентификатор, выопределяющий класс, все, что вам нужно запомнить, это то, что вы:

нужно полное определение, чтобы использовать сам тип в определенияхуйти только с объявлением, чтобы использовать сам тип в объявленияхизбегайте только декларации, когда вы используете только указатели и ссылки и не пытаетесь получить доступ к элементам или вложенным типам (что-либо с., ->, а также:: спереди)

Да, вам придется

#include "B.h"

если вы хотите включить B в свой класс A.

Ваш ответ на вопрос