crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> class QPushButton вместо include <QPushButton>, class VS #include
dsp
  опции профиля:
сообщение 9.2.2011, 0:14
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 51
Регистрация: 12.10.2010
Пользователь №: 2109

Спасибо сказали: 4 раз(а)




Репутация:   0  


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

т.е.

#include <QPushButton>
#include <QLabel>
,

а пишутся так:

class QPushButton;
class QLabel;


и т.д.

с чем это связано? и что использовать?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 9.2.2011, 0:31
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2906
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


это форварды (предопределения) классов для возможности применить паттерн проектирования pimpl (pointer to implementation) . Правда, форварды и не только для этого используются.

А упомянутый паттерн имеет и плюсы, и минусы, поэтому совсем бездумно каждый раз повсюду применять не стоит )

Нормальную статью я с ходу не нашёл. Поищи в тырнете , почитай
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 9.2.2011, 0:39
Сообщение #3


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


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

В заголовочном файле (.h) часто ничего не нужно знать о классе, кроме того что он существует.
Поэтому делается предварительное объявление класса class QPushButton.
А вот в файле реализации (.cpp), уже подключаются подробности #include <QPushButton>
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 9.2.2011, 6:19
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9666
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Существенная оговорка.
Предварительное объявление годится только в случае, если в заголовочнике объявляется ссылка или указатель на некий класс. Тогда компилятору достаточно сказать "такой-то класс действительно существует". Т.к. и ссылка и указатель на данной конкретной платформе всегда одинаковое кол-во байт занимает.

Если же ты используешь класс для наследования, или для создания переменной на стеке (обычной) или используешь члены некого класса, то придётся использовать инклюд. Иначе компилятор не будет ничего знать об особенностях класса.

Примеры, когда без инклюда нельзя
#include <SameClass>

class SubClass : public SameClass
{

...
}
#include <SameClass>

class MyClass
{
...
private:
SameClass var;
}
#include <SameClass>

class MyClass
{
...
public:
    SameClass func_1(); // возвращает значение
    
    func_2(SameClass var); // принимает значение
}
#include <SameClass>

class MyClass
{
...
public:
    SameClass func_1(SameClass *var)
    {
        var->method(); // обращение к члену класса
    }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 9.2.2011, 9:03
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2906
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Цитата(dsp @ 9.2.2011, 2:14) *
class VS #include

блин, я долго думал, при чём тут студия :D А "versus" пишется маленькими буквами

Цитата(Litkevich Yuriy @ 9.2.2011, 8:19) *
Если же ты используешь класс для наследования, или для создания переменной на стеке (обычной) или используешь члены некого класса, то придётся использовать инклюд.

...но при суровой необходимости и это можно обойти :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 9.2.2011, 20:40
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9666
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Алексей1153 @ 9.2.2011, 11:03) *
.но при суровой необходимости и это можно обойти
как?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 10.2.2011, 8:16
Сообщение #7


фрилансер
******

Группа: Участник
Сообщений: 2906
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Litkevich Yuriy,

например так
хотим класс QMyLineEdit:public QLineEdit

QMyLineEdit.h
class QMyLineEdit;

struct QMyLineEditWrapper
{
   QMyLineEdit* p;
   QMyLineEditWrapper(QWidget* parent=0);
};



QMyLineEdit.cpp
#include "QMyLineEdit.h"
#include <QLineEdit>

class QMyLineEdit:public QLineEdit
{
    Q_OBJECT
public:
    explicit QMyLineEdit(QWidget* parent=0):QLineEdit(parent)
    {
    }
    
    QString text() const;//"трамплин"
};

struct QMyLineEditWrapper
{
   QMyLineEdit* p;
   QMyLineEditWrapper(QWidget* parent):p(new QMyLineEdit(parent))
   {
   }
  
   ~QMyLineEditWrapper()
   {
       delete p;
   }
      
   QString text() const
   {
       return p->text();
   }
};


но тут есть один жёсткий минус - для всех нужных функций нужно будет делать эти трамплины
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 10.2.2011, 10:29
Сообщение #8


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(Litkevich Yuriy @ 9.2.2011, 20:40) *
как?

проще говоря, дублированием интерфейса.
в заголовочнике только класс с указателем внутри и форвардом класса этого указателя, а так же все желаемые методы продублированы. в cpp наследуешься, а в реализации дублирующих методов вызываешь соответсвующие методы наследника.
пример: допустим ты хочешь спрятать наследование в срр файл.
заголовочник iface.h
class CImpl;

class IFace
{
  CImpl* impl_;

public:
  IFace();
  ~IFace();

void one();
void two();
void three();

};


реализация
# include "iface.h"

class CImpl : public Anything
{
public:
void one();
void two();
void three();
};

void  IFace::one()
{
  return impl_->one();
}

void IFace::two()
{
  return impl_->two();
}

void IFace::three()
{
  return impl_->three();
}


Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 10.2.2011, 11:28
Сообщение #9


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Цитата(Алексей1153 @ 9.2.2011, 10:03) *
Цитата(Litkevich Yuriy)

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

...но при суровой необходимости и это можно обойти

Если класс используется для наследования (и далее по тексту), хидер включать необходимо. И легальными средствами имхо это не обойти. Компилятор должен обладать информацией о том, что это за класс.

Может я жестко туплю конечно, либо придираюсь... А в чем приведенный код Алексей1153, kwisp, позволяет обойти то, о чем говорит Litkevich Yuriy? То что вы приводите, называется паттерн проектирования пимпл - ака идиома скрытой реализации. Мне кажется это не есть обход в том смысле в котором имеется ввиду.

Ведь можно не создавать объект на стеке в капсуле класса, а использовать указатель на него. Наследование можно опять-таки заменить через указатель (практически всегда). И тогда тоже не нужно будет подключать хидер с капсулой класса в своем хидере. Вопрос ведь какой, как сделать так, чтобы при наследовании или создании объекта класса на стеке не нужно было включать хидер класса. Держу пари что как-то можно. Но схоу не могу сообразить. Вероятно, тут будет что-то из жесткого хака (типа define private public)...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 10.2.2011, 11:33
Сообщение #10


фрилансер
******

Группа: Участник
Сообщений: 2906
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Rocky,
Цитата(Rocky @ 10.2.2011, 13:28) *
хидер включать необходимо

да, но включать его надо уже только в файл реализации :)

Цитата(Rocky @ 10.2.2011, 13:28) *
А в чем приведенный код Алексей1153, kwisp, позволяет обойти

а обходить в данном случае не нужно. Это было сказано о случае СУРОВОЙ необходимости )) То есть - костыль

Цитата(Rocky @ 10.2.2011, 13:28) *
Наследование можно опять-таки заменить через указатель (практически всегда).

оу, расскажи, как ?. Особенное внимание удели конструктору, деструктору и виртуальным функциям

Сообщение отредактировал Алексей1153 - 10.2.2011, 11:34
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 17.1.2021, 19:10