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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [решено] Область видимости  (Прочитано 6796 раз)
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« : Март 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 надо указать что-то другое.
« Последнее редактирование: Март 21, 2010, 13:37 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Март 19, 2010, 17:08 »

во-первых, класс ThreadManager, не наследник QObject, и от макроса Q_OBJECT толку никакого
во-вторых, пиши объявление класса (наследника QObject) в h-файле, а реализацию в cpp-файле, это от многих головников избавит.

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

Юра.
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #2 : Март 19, 2010, 17:29 »

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

kubuntu/Win7/x64/NetBeans
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #3 : Март 19, 2010, 17:40 »

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

Юра.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Март 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 (вместо предварительного описания), что чуть менее теоретично и увеличивает время компиляции.
« Последнее редактирование: Март 19, 2010, 18:53 от Igors » Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #5 : Март 19, 2010, 19:01 »

Конечно же я пробовал #include "MainForm.h" для файла ThreadManager.h, не помогает. Да и по логике вещей: в MainForm.h будет заинклуден ThreadManager.h, а в ThreadManager.h - MainForm.h. Ерунда какая-то...
Записан

kubuntu/Win7/x64/NetBeans
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Март 19, 2010, 19:16 »

Конечно же я пробовал #include "MainForm.h" для файла ThreadManager.h, не помогает. Да и по логике вещей: в MainForm.h будет заинклуден ThreadManager.h, а в ThreadManager.h - MainForm.h. Ерунда какая-то...
Конечно не поможет если в MainForm.h будет заинклуден ThreadManager.h. Ведь тогда сработает "страж включения" (#ifndef). Делайте по классике - переносите тела в cpp а там уже вставляйте любые #include
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #7 : Март 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-файлы, чтобы не путаться потом? Как вообще в с++ принято организовывать подобную структуру хранения?
« Последнее редактирование: Март 19, 2010, 20:38 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
niXman
Гость
« Ответ #8 : Март 19, 2010, 21:05 »

а про extern все забыли? Подмигивающий
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #9 : Март 19, 2010, 21:59 »

>>а про extern все забыли?
я забыл как про страшный сон, перейдя на С++
Записан

Юра.
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #10 : Март 19, 2010, 22:02 »

serg_hd, Си и Си++, не модульные языки программирования. не существует понятия модуля (как, например, в python, про яву я не вкурсе), как единицы компиляции

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

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

« Последнее редактирование: Март 19, 2010, 22:05 от lit-uriy » Записан

Юра.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Март 19, 2010, 22:18 »

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

Сообщений: 668



Просмотр профиля
« Ответ #12 : Март 21, 2010, 13:36 »

всё понял, всем спасиб
Записан

kubuntu/Win7/x64/NetBeans
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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