Russian Qt Forum

Qt => Общие вопросы => Тема начата: serg_hd от Март 19, 2010, 16:44



Название: [решено] Область видимости
Отправлено: serg_hd от Март 19, 2010, 16:44
Вот и я решил перейти с java на с++, не в последнюю очередь из-за Qt. Это конечно меня весьма радует, но и головной боли добавило.
Есть 2 заголовочных файла, в которых кроме инициализации лежит и реализация, писались не с помощью Creator'a. Проблема в том, что не знаю как из класса 2го файла обратится к объекту класса (главному окну) 1го файла:
MainForm.h:
Код:
#ifndef _UI_FORM_H
#define _UI_FORM_H

#include <QMainWindow>
#include <QDesktopWidget>
#include <QApplication>
#include <QSplashScreen>
#include <QTabWidget>
#include <QString>
#include <iostream>
#include "ThreadManager.h"

class MainWindow: public QMainWindow
{
 Q_OBJECT

 public:
  MainWindow(QWidget *parent = 0): QMainWindow(parent), tabWidget(this)
   {
    // тут работа с виджетами: добавление, установка параметров и т.п.
   this->tabWidget.addTab(&executeTab, tr("tabname));
   }

 QTabWidget tabWidget;
 QWidget executeTab;
};

//класс, объект которого создаю в main.cpp
class MainForm
{
 public:
  MainWindow mainWindow;
  ThreadManager threadManager;

  MainForm(QWidget* parent = 0): mainWindow(parent), threadManager(&this->mainWindow)
  {
    this->mainWindow.show(); //отображение главного окна со всеми виджетами
  }
};
#endif /* _UI_FORM_H */

Файл ThreadManager.h:
Код:
#ifndef _THREADMANAGER_H
#define _THREADMANAGER_H

class MainWindow;

class ThreadManager
{
 Q_OBJECT

 public:
  MainWindow* _mainWindow;

 ThreadManager(MainWindow* mainWindow): _mainWindow(mainWindow)
 {
  
    /* тут, если не закомментить строку ниже будет ошибка "./webcruiser/ThreadManager.h:22: error: invalid use of incomplete type 'struct MainWindow' ./ThreadManager.h:11: error: forward declaration of 'struct MainWindow' */

   this->_mainWindow->tabWidget.setCurrentIndex(0);
 }
};

#endif /* _THREADMANAGER_H */

Что не так? Подозреваю что вместо "class MainWindow;" в ThreadManager.h надо указать что-то другое.


Название: Re: Область видимости
Отправлено: lit-uriy от Март 19, 2010, 17:08
во-первых, класс ThreadManager, не наследник QObject, и от макроса Q_OBJECT толку никакого
во-вторых, пиши объявление класса (наследника QObject) в h-файле, а реализацию в cpp-файле, это от многих головников избавит.

В h-файле делаешь предварительное объявление (forward declaration):
class MainWindow;
, а в cpp-файле подключаешь его заголовочник:
#include "MainWindow.h"


Название: Re: Область видимости
Отправлено: serg_hd от Март 19, 2010, 17:29
А в случае с ThreadManager  вообще надо наследоваться от QObject (Q_OBJECT я пока убрал)? Если да, то зачем? В конструктор я просто передаю указатель на главное окно, не понимаю почему ошибка.


Название: Re: Область видимости
Отправлено: lit-uriy от Март 19, 2010, 17:40
А в случае с ThreadManager  вообще надо наследоваться от QObject (Q_OBJECT я пока убрал)? Если да, то зачем?
надо если тебе нужна его функциональность, например:
сигналы и слоты,
родственные отношения объектов - можно создать объект динамически передав ему родителя, и тогда родитель будет отвечать за время жизни объекта, его не нужно будет удалять вручную. (в Ява, ты этого вообще никогда не делаешь, т.к. есть сборщик мусора)
В конструктор я просто передаю указатель на главное окно, не понимаю почему ошибка.
"...incomplete type 'struct MainWindow'", т.е. тип не известен, о нём лишь сказано, что есть, но его описания нет


Название: Re: Область видимости
Отправлено: Igors от Март 19, 2010, 18:51
В конструктор я просто передаю указатель на главное окно, не понимаю почему ошибка.

Код:
Файл ThreadManager.h:
#ifndef _THREADMANAGER_H
#define _THREADMANAGER_H

class MainWindow;

class ThreadManager
{
...
В данном случае "class MainWindow" есть предварительное описание. Вы можете использовать указатели и ссылки на MainWindow, но никакие подробности этого класса еще неизвестны и вызовут ошибку компиляции. Стандартный подход как у Вас, но тело конструктора ThreadManager находится в cpp файле, там же строка
Код:
#include "MainWindow.h"
Тогда имеется полное описание MainWindow и все его publc члены доступны. Можно сделать #include и в ThreadManager.h (вместо предварительного описания), что чуть менее теоретично и увеличивает время компиляции.


Название: Re: Область видимости
Отправлено: serg_hd от Март 19, 2010, 19:01
Конечно же я пробовал #include "MainForm.h" для файла ThreadManager.h, не помогает. Да и по логике вещей: в MainForm.h будет заинклуден ThreadManager.h, а в ThreadManager.h - MainForm.h. Ерунда какая-то...


Название: Re: Область видимости
Отправлено: Igors от Март 19, 2010, 19:16
Конечно же я пробовал #include "MainForm.h" для файла ThreadManager.h, не помогает. Да и по логике вещей: в MainForm.h будет заинклуден ThreadManager.h, а в ThreadManager.h - MainForm.h. Ерунда какая-то...
Конечно не поможет если в MainForm.h будет заинклуден ThreadManager.h. Ведь тогда сработает "страж включения" (#ifndef). Делайте по классике - переносите тела в cpp а там уже вставляйте любые #include


Название: Re: Область видимости
Отправлено: serg_hd от Март 19, 2010, 20:22
Конечно же я пробовал #include "MainForm.h" для файла ThreadManager.h, не помогает. Да и по логике вещей: в MainForm.h будет заинклуден ThreadManager.h, а в ThreadManager.h - MainForm.h. Ерунда какая-то...
Конечно не поможет если в MainForm.h будет заинклуден ThreadManager.h. Ведь тогда сработает "страж включения" (#ifndef). Делайте по классике - переносите тела в cpp а там уже вставляйте любые #include
т.е. другого варианта кроме как использовать классику нет?
Хорошо, тогда другой вопрос. Допустим в проекте у меня 50 файлов (на данный момент именно .h-файлов и 1, главный .cpp). Мне их надо раскидать "по тематике". В яве это, например, пакеты. Т.е. в проекте может быть несколько файлов с одинаковыми названиями, но за счёт того, что они лежат в разных пакетах конфликтов не будет, просто при использовании указывается полный путь. А как это организовать в случае прокта с++? Раскидать .h-файлы по разным физ. каталогам ("пакетам", сейчас у меня так сделано), а куда тогда ложить cpp-файлы, чтобы не путаться потом? Как вообще в с++ принято организовывать подобную структуру хранения?


Название: Re: Область видимости
Отправлено: niXman от Март 19, 2010, 21:05
а про extern все забыли? ;)


Название: Re: Область видимости
Отправлено: lit-uriy от Март 19, 2010, 21:59
>>а про extern все забыли?
я забыл как про страшный сон, перейдя на С++


Название: Re: Область видимости
Отправлено: lit-uriy от Март 19, 2010, 22:02
serg_hd, Си и Си++, не модульные языки программирования. не существует понятия модуля (как, например, в python, про яву я не вкурсе), как единицы компиляции

Ты должен понять простую вещь:
директива препроцессора include, должна тобой восприниматься буквально. Т.е. вместо неё будет помещено всё содержимое указанного файла.
Компиляции, обычно, подвергаются только файлы с/cpp, из них получаются объектные файлы, затем линкер их соединяет, по одинаковым идентификаторам (именам функций, переменных, классов). Поэтому не должно быть два одинаковых имени выражающих разные вещи.

Это дерьмовая идея, но это так. И исходя из того как работает include посмотри? какие файлы в итоге получаются, для случая:
1) используется разделение на h и cpp.
2) в твоём исходном варианте.



Название: Re: Область видимости
Отправлено: Igors от Март 19, 2010, 22:18
т.е. другого варианта кроме как использовать классику нет?
Общий принцип - переменная должна быть описана до того как используется. Если у Вас 2 класса - и оба хотят знать друг о друге все (прямо здесь, в описании) - ходов нет, это нормально/естественно. Вообще лепить в хедер содержательные ф-ции - не гуд (если это не template). Использование extern в данном случае никак не поможет, тип все равно нужен.
Хорошо, тогда другой вопрос. Допустим в проекте у меня 50 файлов (на данный момент именно .h-файлов и 1, главный .cpp). Мне их надо раскидать "по тематике". В яве это, например, пакеты. Т.е. в проекте может быть несколько файлов с одинаковыми названиями, но за счёт того, что они лежат в разных пакетах конфликтов не будет, просто при использовании указывается полный путь. А как это организовать в случае прокта с++? Раскидать .h-файлы по разным физ. каталогам ("пакетам", сейчас у меня так сделано), а куда тогда ложить cpp-файлы, чтобы не путаться потом? Как вообще в с++ принято организовывать подобную структуру хранения?
Я работаю в IDE, часто организация файлов в проекте - просто копия файловой структуры. Все же файлов с одинаковыми именами лучше (практичнее) избегать. Компилятор ищет h файлы их в Include Paths и будет найден только первый. Чтобы не запутаться нужно писать типа #include "./Package1/matrix.h"


Название: Re: Область видимости
Отправлено: serg_hd от Март 21, 2010, 13:36
всё понял, всем спасиб