Russian Qt Forum

Программирование => С/C++ => Тема начата: trot от Февраль 10, 2011, 22:56



Название: Объявление класса
Отправлено: trot от Февраль 10, 2011, 22:56
Поясните пожайлуста зачем в некоторых случаях когда в классе А объявляется переменная класса В, то необходимо
перед объявлением класса А писать class B. Например
Код:
class B;

class A{
    A();
    ~A();

    B *b;
}


Название: Re: Объявление класса
Отправлено: Akon от Февраль 10, 2011, 23:30
Опережающее объявление класса. Заголовочный файл этого класса подключается в файл реализации. Данная техника уменьшает зависимости заголовочных файлов, что довольно значительно может уменьшать время компиляции. Повсеместно используется в Qt.

В случаях циклических зависимостей опережающее описание также необходимо.


Название: Re: Объявление класса
Отправлено: blood_shadow от Февраль 11, 2011, 00:55
Поясните пожайлуста зачем в некоторых случаях когда в классе А объявляется переменная класса В, то необходимо
перед объявлением класса А писать class B. Например
попросту говоря компилятор не знает что это за тип "B" и вообще что это такое, если не написать предварительное объявление этого типа


Название: Re: Объявление класса
Отправлено: serg_hd от Февраль 11, 2011, 00:57
Поясните пожайлуста зачем в некоторых случаях когда в классе А объявляется переменная класса В, то необходимо
перед объявлением класса А писать class B. Например
Код:
class B;

class A{
    A();
    ~A();

    B *b;
}

не переменная, а указатель. В случае указателя это работает, т.к. для него не обязательно наличие описания тела объекта на который он будет указывать. А при создании объекта обязательно его описание тела (чтобы компилятор знал сколько памяти под него выделить). Был бы это не указатель, не прокатило бы, т.к. понадобилось бы описание класса B для выделения памяти этому члену класса. А ещё прокатит не только для указателя, но и в случае когда B это тип возвращаемого значения:
Код
C++ (Qt)
class B;
class A{
public:
   A();
   ~A();
   B method();
}
 


Название: Re: Объявление класса
Отправлено: trot от Февраль 12, 2011, 16:55
Получается так, что  подключить заголовочный файл - #include "B.h" не достаточно, что бы найти описание класса, еще необходимо прописать class B. Не понимаю тогда роли конструкции #include.


Название: Re: Объявление класса
Отправлено: Fat-Zer от Февраль 12, 2011, 18:07
это пишется как раз, что бы не подключать хедер B.h в A.h, а включить только в A.cpp


Название: Re: Объявление класса
Отправлено: blood_shadow от Февраль 13, 2011, 15:00
Получается так, что  подключить заголовочный файл - #include "B.h" не достаточно, что бы найти описание класса, еще необходимо прописать class B. Не понимаю тогда роли конструкции #include.

смотри пост Fat-Zer и мой пост выше, там все указано

приведу пример, если у тебя есть заголовочные файлы A.h и B.h и файлы реализаций соответственно A.cpp и B.cpp, при компиляции будет создано две единицы компиляции A.o(A.h + A.cpp) и B.o(B.h + B.cpp), потом компоновщик их свяжет в один исполняемый файл, но так как ты в классе А(в хэдере, не подключая B.h) используешь объявление указателя на переменную класса B, то компилятор не знает на этапе компиляции что такое класс B(он объявлен в другой единицы компиляции) и потому ты должен сказать компилятору что класс B - некий тип данных который будет определен позже

p.s. предварительное объявление как раз и нужно чтоб в A.h не пихать еще и B.h с помощью инклуда(короче говоря предварительное объявление похоже на спецификатор extern). Было бы не плохо если ты б разобрался в компоновке, единицах компиляции и вообще процесу сборки программы


Название: Re: Объявление класса
Отправлено: trot от Февраль 13, 2011, 18:50
В том-то вся и проблема есть "#include B.h" и пока не напишешь class B программа не собирается. Правда для того простого случая что я привел, достаточно того что вы сказали, а когда куча классов и все они переплетаются почему-то надо писать именно два раза.
Для этого случая Akon разъяснил
Цитировать
В случаях циклических зависимостей опережающее описание также необходимо.
Все спасибо.


Название: Re: Объявление класса
Отправлено: SASA от Февраль 14, 2011, 11:59
а когда куча классов и все они переплетаются
Надо их распутывать. Если появляются циклические зависимости, то это подвод задуматься об архитектуре.


Название: Re: Объявление класса
Отправлено: Fat-Zer от Февраль 14, 2011, 12:26
Надо их распутывать. Если появляются циклические зависимости, то это подвод задуматься об архитектуре.
знаю один(и только один) случай, когда это действительно необходимо... классический пример: узел дерева наследуется от листа, лист  имеет указатель на родителя(на узел), у родителя есть список потомков(в общем случае листьев)...


Название: Re: Объявление класса
Отправлено: SASA от Февраль 14, 2011, 15:13
знаю один(и только один) случай, когда это действительно необходимо... классический пример: узел дерева наследуется от листа, лист  имеет указатель на родителя(на узел), у родителя есть список потомков(в общем случае листьев)...

И то не всегда. Может стоит объявить общий интерфейс для парента и потомков. Например, патерн "Компоновщик".


Название: Re: Объявление класса
Отправлено: Fat-Zer от Февраль 14, 2011, 17:24
И то не всегда. Может стоит объявить общий интерфейс для парента и потомков. Например, патерн "Компоновщик".
его и подразумевал... в нём тоже можно  делать ссылки на родителей. и родитель всегда типа "композит"


Название: Re: Объявление класса
Отправлено: Akon от Февраль 15, 2011, 19:57
Циклические зависимости иногда неизбежны. Рвутся опережающим описанием. Правильно упомянули компоновщик - первым приходит на ум когда слышишь "циклическая зависимость".