crossplatform.ru

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

3 страниц V   1 2 3 >  
Ответить в данную темуНачать новую тему
daorus
  опции профиля:
сообщение 30.10.2010, 20:18
Сообщение #1


Студент
*

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

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




Репутация:   0  


Какой синтаксис форвад-декларации для типа хеш, если я хочу в классе хранить на него указатель

// my.h
class QHash; // не хватает
class QString; // хватает
class my
{
    public:
    my();
    QHash<QString, QString>* dic;
};

// my.cpp
#include <QHash>
my::my()
{
    dic = new QHash<QString, QString>;
}


Сообщение отредактировал Litkevich Yuriy - 30.10.2010, 20:27
Причина редактирования: Перенёс, так как относится не к Qt, а к Си++
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 30.10.2010, 20:25
Сообщение #2


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

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

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




Репутация:   34  


помести
#include <QHash>
#include <QString>
в заголовочный файл

ну а если поизвращаться всё равно надо, то сделай класс-оболочку, а вот его уже форвардни :)

Сообщение отредактировал Алексей1153 - 30.10.2010, 20:26
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 30.10.2010, 20:30
Сообщение #3


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

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

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




Репутация:   94  


Здесь для QString этот номер не пройдёт, т.к. используются не указатели на него.

Вообще forward declaration возможен только в случае применения указателей. Т.к. их размер (в памяти) постоянен
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 30.10.2010, 20:33
Сообщение #4


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

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

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




Репутация:   23  


интересный вопрос. что на данный вопрос отвечает гугл?
просто так пальцем в небо.
template <>
class QHash<QString, QString>;
не схавает?
а вообще конечно - такого рода штуки могут быть непереносимы так что, можно и отказаться от такого рода forward declaration

Цитата(Litkevich Yuriy @ 30.10.2010, 21:30) *
в случае применения указателей.

а ссылок?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 30.10.2010, 20:46
Сообщение #5


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

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

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




Репутация:   94  


Цитата(kwisp @ 30.10.2010, 23:33) *
а ссылок?
тут не уверен, возможно, тоже пройдёт
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 30.10.2010, 20:51
Сообщение #6


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

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

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




Репутация:   34  


ссылка - также, как и указатель. Потому что это одно и тоже для компилятора :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 30.10.2010, 21:25
Сообщение #7


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

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

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




Репутация:   29  


Цитата(daorus @ 30.10.2010, 21:18) *
Какой синтаксис форвад-декларации для типа хеш, если я хочу в классе хранить на него указатель
Да все просто на самом деле

class QString;
template <class Key, class T>
class QHash;

class my
{
    public:
    my();
    QHash<QString, QString>* dic;
};

// my.cpp
#include <QHash>
my::my()
{
    dic = new QHash<QString, QString>;
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 30.10.2010, 21:52
Сообщение #8


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

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

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




Репутация:   34  


Игорь, сильно сомневаюсь

template <class Key, class T>
class QHash;

QHash<QString, QString>* dic;

а ты проверил, компилится ?

Будет ведь переопределение класса QHash из его инклуда

Сообщение отредактировал Алексей1153 - 30.10.2010, 21:53
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 30.10.2010, 22:07
Сообщение #9


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

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

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




Репутация:   29  


Цитата(Алексей1153 @ 30.10.2010, 22:52) *
Игорь, сильно сомневаюсь
На всякий случай проверил, все работает. Хотя и так знал. В исходниках Qt довольно часто используется такое предварительное объявление шаблонных классов.

Цитата(Алексей1153 @ 30.10.2010, 22:52) *
Будет ведь переопределение класса QHash из его инклуда
Вообще этой фразы не понял. Какое еще переопределение?
В .h файле нам всего лишь нужно указать тип класса. Никаких уточнений не нужно, так как создается указатель и инстанцирования не происходит. В момент инстанцирования вся информация о параметрах шаблона уже есть
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 30.10.2010, 22:15
Сообщение #10


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

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

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




Репутация:   34  


igor_bogomolov, всё, дошло до меня :) Я просто никогда так не предопределял шаблоны
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
daorus
  опции профиля:
сообщение 31.10.2010, 0:00
Сообщение #11


Студент
*

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

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




Репутация:   0  


Цитата(igor_bogomolov @ 31.10.2010, 0:25) *
Да все просто на самом деле
Круто. Огромное спасибо!

====

Раз уж тут чисто по синтаксису вопрос задал. Есть один вопрос, не знаю где спросить. Вот грядет стандарт С+. Там есть лямбды, т.е. функции без сигнатур. А они вообще в кути могут хоть какую-то полезную нагрузку нести или эти лямбды - это просто "с боку бантик"? Сорри за оффтопик, есличо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 31.10.2010, 0:45
Сообщение #12


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

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

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




Репутация:   94  


daorus, лучше следовать правилу:
Одна проблема (вопрос) - одна тема. Так потом проще искать, если приспичит
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 31.10.2010, 11:08
Сообщение #13


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

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

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




Репутация:   12  


Цитата(daorus @ 30.10.2010, 22:18) *
Какой синтаксис форвад-декларации для типа хеш, если я хочу в классе хранить на него указатель

а где в приведённом коде форвард-декларация-то? форвард-декларацией называется случай, когда класс ссылается сам на себя или на потомков. ну и всё сказанное (насчёт указателей) тогда справедливо. но в примере никакой форвард-декларации нет. обычное использование шаблонного класса. стандартного инклюда должно хватить. главное, если компилить под вендой, с MSVC, то нельзя выносить реализацию шаблонного класса из его объявления (это баг MSVC, несовместимость со стандартами). то есть, в заголовочнике должен быть весь класс и заголовочник должен быть указан до использования где-либо в коде.

Сообщение отредактировал Iron Bug - 31.10.2010, 11:09
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 31.10.2010, 11:30
Сообщение #14


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

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

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




Репутация:   94  


Цитата(Iron Bug @ 31.10.2010, 14:08) *
когда класс ссылается сам на себя или на потомков
не только. Любой другой класс тоже может быть использован.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 31.10.2010, 11:34
Сообщение #15


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

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

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




Репутация:   34  


Цитата(Iron Bug @ 31.10.2010, 14:08) *
то есть, в заголовочнике должен быть весь класс и заголовочник должен быть указан до использования где-либо в коде.

о да. Столкнулся несколько раз, пытался решить, спрашивал советы - так и оставил в заголовочнике весь шаблон.
Но душа то не удовлетворена ))) Изворачивался-таки, разделял шаблон на шаблонную составляющую и обычную. Последняя составляющая обычно гораздо объёмнее шаблонной, так что оно того стОило :) Для разделения применялись все нечестные приёмы: преобразование указателя к void* , указатель на коллбэк, так же преобразованный к void*, а где надо - приводимый к нужному указателю
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
daorus
  опции профиля:
сообщение 31.10.2010, 11:55
Сообщение #16


Студент
*

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

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




Репутация:   0  


Iron Bug, во-первых, привет земляку. Я тоже из Екатеринбурга.
Цитата
но в примере никакой форвард-декларации нет

Форвард-декларация - это такой способ сэкономить время на компилции. Форвард декларация - это простое сообщение о существовании сигнатуры. А декларация - это подробное разъяснение, что за этой сигнатурой скрывается. Форвард-деклараци - это любая функция или класс, в синтаксисе которых отсутствуют фигурные скобки - это основной признак форвад-декларации. Исторически появились как необходимость кросс-вставки классов.
class A { B b }; class B { A a }; // error
// вот и появилась форвард-декларация
class B; class A { B b; }; class B { A a; }; // ok
// на самом деле тоже не ок, для ок'я нужны указатели, см. ниже

Ну а сегодня, её юзают тупо для сокращения времени компиляции, если есть возможность обойтись одними указателями на класс или функцию, потому что размер указателя вне зависимости от типа есть константа.
class B; class A { B* b; }; // ok
class B; class A { B b; }; // error
class B{}; class A { B b; }; // ok


Топик начался с того, что для шаблонных классов создание обычной декларации не катит, а как катит я не знал. И тут мне на форуме подсказали супер-мегафичу, которую я домыслил и оказалось, что для шаблонов форвард-декларацией является как бы создание экземлпяра шаблона! + кстати, подсказанный пример можно существенно сократить, выкинув сигнатуры классов в шаблоне KEY, T. Главное - сохранить кол-во классов в шаблоне.

class a; // обычный форвард
template<class, class> b; // шаблонный форвард

class A { a* ptr; }; // юз обычного класса
class B { b<a,a>* ptr; }; // юз шаблонного
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 31.10.2010, 12:08
Сообщение #17


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

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

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




Репутация:   12  


Цитата(daorus @ 31.10.2010, 13:55) *
Исторически появились как необходимость кросс-вставки классов.

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

Цитата(Алексей1153 @ 31.10.2010, 13:34) *
о да. Столкнулся несколько раз, пытался решить, спрашивал советы - так и оставил в заголовочнике весь шаблон.

я как-то тоже напоролась на это. это баг мелкософта. об этом написано где-то в MSDN, только мелким-мелким шрифтом на страничке, которую так просто и не найти :) там порядка восьми несовместимостей со стандартом у них имеется. в прочих компилерах этого нет.

Цитата(daorus @ 31.10.2010, 13:55) *
Топик начался с того, что для шаблонных классов создание обычной декларации не катит, а как катит я не знал. И тут мне на форуме подсказали супер-мегафичу, которую я домыслил и оказалось, что для шаблонов форвард-декларацией является как бы создание экземлпяра шаблона! + кстати, подсказанный пример можно существенно сократить, выкинув сигнатуры классов в шаблоне KEY, T. Главное - сохранить кол-во классов в шаблоне.

всё объясняется проще: когда мелкософтовский компилер собирает модули, он считает, что если нет экземпляра шаблонного класса - то его описание можно просто выкинуть. это и есть баг компилера, его несоответствие стандарту. просто для MSVC нужно, чтобы либо инклюд был явно включен в файл, где шаблон будет использован, либо вот так вот, как ты описал, извратиться и заставить компилер учесть шаблонный класс методом создания фиктивного объекта.

Сообщение отредактировал Iron Bug - 31.10.2010, 12:25
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 31.10.2010, 12:52
Сообщение #18


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

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

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




Репутация:   34  


экономия времени будет. По крайней мере в студии это очень заметно :)

Например, класс A (не шаблон), описанный в хедере, не используется в некоем cpp, но из-за вложенности хедеров попал в начало этого cpp. Компилятор его лишний раз скомпилирует (потому что это только у шаблонов не компилируется неиспользыемое).

В случае же разнесения кода по A.h и A.cpp , компиляция пройдёт шустрее, так как компилироваться класс A будет всего один раз.

Проверить можно так: пусть класс A целиком сидит в A.cpp

Можно написать в любой его функции строчку
{int i;} //компилятор выдаст предупреждение, что не использована переменная


Везде, где инклуд A.h используется, предупреждение появится (ровно столько же раз, сколько заинклужено)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 31.10.2010, 13:34
Сообщение #19


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

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

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




Репутация:   29  


Цитата(Iron Bug @ 31.10.2010, 11:08) *
с MSVC, то нельзя выносить реализацию шаблонного класса из его объявления (это баг MSVC, несовместимость со стандартами). то есть, в заголовочнике должен быть весь класс
Цитата(Алексей1153 @ 31.10.2010, 11:34) *
так и оставил в заголовочнике весь шаблон
При чем здесь MSVC? Разделить реализацию и объявление шаблона можно только с использованием ключевого слова export, которое ни один компилятор так и не реализовал. Поэтому для шаблонов подходит только модель включения, т.е. в одном файле должны быть все объявления и определения шаблона. У Вандевурда & Джосатиса это хорошо описано.

Цитата(daorus @ 31.10.2010, 11:55) *
template<class, class> b; // шаблонный форвард
Тут ошибка, должно быть template<class, class> class b;

Кстати, по поводу того зачем нужны форвард объявления хорошо описано в этой книге (ссылка) (см. раздел 2.3)

--Добавлено чуть позже--------------------------------------------------------------------------

Этого вообще не понял
Цитата(Iron Bug @ 31.10.2010, 12:08) *
всё объясняется проще: когда мелкософтовский компилер собирает модули, он считает, что если нет экземпляра шаблонного класса - то его описание можно просто выкинуть. это и есть баг компилера, его несоответствие стандарту. просто для MSVC нужно, чтобы либо инклюд был явно включен в файл, где шаблон будет использован, либо вот так вот, как ты описал, извратиться и заставить компилер учесть шаблонный класс методом создания фиктивного объекта.

Разберем по частям
Цитата
когда мелкософтовский компилер собирает модули, он считает, что если нет экземпляра шаблонного класса - то его описание можно просто выкинуть.
совершенно правильно считает
Цитата
просто для MSVC нужно, чтобы либо инклюд был явно включен в файл, где шаблон будет использован
а как вы собираетесь использовать класс, если в данном листе трансляции ничего про него не известно? Естественно нужно делать инклуд, и шаблоны тут не при чем

Цитата
либо вот так вот, как ты описал, извратиться и заставить компилер учесть шаблонный класс методом создания фиктивного объекта
какой еще фиктивный объект? Где вы его увидели? Там лишь форвард объявление шаблонного класса, никаких объектов не создается
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
daorus
  опции профиля:
сообщение 31.10.2010, 13:47
Сообщение #20


Студент
*

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

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




Репутация:   0  


Цитата(Iron Bug @ 31.10.2010, 14:08) *
достигается вставкой инклюда в одном месте кода
У меня почему-то активное использование форвардов существенно экономит время компиляции. + если зависимость от форварда, то изменение в заголовочном файле не генерит флаг на перекомпиляцию. А вообще это просто вопрос привычки. Привык я форвары в хедерах юзать вместо инклудов. :-)
Цитата(Iron Bug @ 31.10.2010, 14:08) *
всё объясняется проще: когда мелкософтовский компилер
а я на g++ работаю. Про msvc вообще ничего не знаю.
Цитата(igor_bogomolov @ 31.10.2010, 15:13) *
Тут ошибка, должно быть template<class, class> class b;
Да, конечно. Я слишком увлекся идеей. Но почему-то у меня нет кнопки правка сообщений, поэтому баг так и останется висеть в моем посте. :-(

Цитата(igor_bogomolov @ 31.10.2010, 15:34) *
с использованием ключевого слова export

Если я правильно понял, это вы уже не про хедеры, а про форварды в *.cpp файлах?
т.е. типа такого
// my.cpp
export template<class, class> class B;
my::my() { B<int, int> b; }

Вы это имели ввиду?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 31.10.2010, 13:50
Сообщение #21


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

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

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




Репутация:   34  


Цитата(daorus @ 31.10.2010, 16:41) *
Привык я форвары в хедерах юзать вместо инклудов. :-)

это не должно быть самоцелью. Частенько в этом нет необходимости, но ведёт к затратам времени на разработку плюс учитывание ручного управления памятью. Причины использовать форвард - это кросс-ссылка или большой объём кода. Других причин не вижу ))
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 31.10.2010, 14:09
Сообщение #22


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

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

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




Репутация:   29  


Цитата(daorus @ 31.10.2010, 13:47) *
Но почему-то у меня нет кнопки правка сообщений
Появится после 20 сообщений.

Цитата(daorus @ 31.10.2010, 13:47) *
Если я правильно понял, это вы уже не про хедеры, а про форварды в *.cpp файлах?
Это я про разделение объявления шаблонного класса и его реализации по .cpp/.h фалам http://www.cppreference.com/wiki/keywords/export (если конечно я правильно идею понял, попробовать, как вы понимаете, это не получится)

Цитата
Привык я форвары в хедерах юзать вместо инклудов. :-)
Аналогично. Если в классе объявленны только ссылки и указатели, не вижу ни какого смысла делать инклуд, только форвард объявление :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 15.6.2025, 22:47