Russian Qt Forum
Ноябрь 24, 2024, 01:08 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Объявление класса  (Прочитано 9318 раз)
trot
Гость
« : Февраль 10, 2011, 22:56 »

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

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

    B *b;
}
Записан
Akon
Гость
« Ответ #1 : Февраль 10, 2011, 23:30 »

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

В случаях циклических зависимостей опережающее описание также необходимо.
Записан
blood_shadow
Гость
« Ответ #2 : Февраль 11, 2011, 00:55 »

Поясните пожайлуста зачем в некоторых случаях когда в классе А объявляется переменная класса В, то необходимо
перед объявлением класса А писать class B. Например
попросту говоря компилятор не знает что это за тип "B" и вообще что это такое, если не написать предварительное объявление этого типа
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #3 : Февраль 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();
}
 
« Последнее редактирование: Февраль 11, 2011, 01:07 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
trot
Гость
« Ответ #4 : Февраль 12, 2011, 16:55 »

Получается так, что  подключить заголовочный файл - #include "B.h" не достаточно, что бы найти описание класса, еще необходимо прописать class B. Не понимаю тогда роли конструкции #include.
Записан
Fat-Zer
Гость
« Ответ #5 : Февраль 12, 2011, 18:07 »

это пишется как раз, что бы не подключать хедер B.h в A.h, а включить только в A.cpp
Записан
blood_shadow
Гость
« Ответ #6 : Февраль 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). Было бы не плохо если ты б разобрался в компоновке, единицах компиляции и вообще процесу сборки программы
Записан
trot
Гость
« Ответ #7 : Февраль 13, 2011, 18:50 »

В том-то вся и проблема есть "#include B.h" и пока не напишешь class B программа не собирается. Правда для того простого случая что я привел, достаточно того что вы сказали, а когда куча классов и все они переплетаются почему-то надо писать именно два раза.
Для этого случая Akon разъяснил
Цитировать
В случаях циклических зависимостей опережающее описание также необходимо.
Все спасибо.
Записан
SASA
Гость
« Ответ #8 : Февраль 14, 2011, 11:59 »

а когда куча классов и все они переплетаются
Надо их распутывать. Если появляются циклические зависимости, то это подвод задуматься об архитектуре.
Записан
Fat-Zer
Гость
« Ответ #9 : Февраль 14, 2011, 12:26 »

Надо их распутывать. Если появляются циклические зависимости, то это подвод задуматься об архитектуре.
знаю один(и только один) случай, когда это действительно необходимо... классический пример: узел дерева наследуется от листа, лист  имеет указатель на родителя(на узел), у родителя есть список потомков(в общем случае листьев)...
Записан
SASA
Гость
« Ответ #10 : Февраль 14, 2011, 15:13 »

знаю один(и только один) случай, когда это действительно необходимо... классический пример: узел дерева наследуется от листа, лист  имеет указатель на родителя(на узел), у родителя есть список потомков(в общем случае листьев)...

И то не всегда. Может стоит объявить общий интерфейс для парента и потомков. Например, патерн "Компоновщик".
Записан
Fat-Zer
Гость
« Ответ #11 : Февраль 14, 2011, 17:24 »

И то не всегда. Может стоит объявить общий интерфейс для парента и потомков. Например, патерн "Компоновщик".
его и подразумевал... в нём тоже можно  делать ссылки на родителей. и родитель всегда типа "композит"
Записан
Akon
Гость
« Ответ #12 : Февраль 15, 2011, 19:57 »

Циклические зависимости иногда неизбежны. Рвутся опережающим описанием. Правильно упомянули компоновщик - первым приходит на ум когда слышишь "циклическая зависимость".
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.118 секунд. Запросов: 23.