![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() |
Litkevich Yuriy |
![]()
Сообщение
#1
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Никак не могу въехать в виртуальный деструктор.
Есть некая программа написанная с использованием Qt, работает стабильно. При развитии программы, она может падать в некий момент времени, обычно при взаимодействии с пользовательским интерфейсом. Но чаще возникает авария при завершении работы. Эту ситуацию можно пердотвратить в ведя в один из классов пустой, ничего не делающий, виртуальный деструктор. Речь идёт о наследнике либо QObject, либо QWidget. Может кто-нибудь объяснить, как может влиять создание руками виртуального деструктора, при условии, что его тело пустое? |
|
|
![]() |
BRE |
![]()
Сообщение
#2
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Ситуация вообще странная.
Насколько я помню, виртуальный деструктор вводиться еще в QObject, т.е. все остальные деструкторы в наследниках (включая QWidget) по умолчанию виртуальные. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#3
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Насколько я помню, виртуальный деструктор вводиться еще в QObject, да, но вот Креатор, например, генерит файлы классов всегда с явно указанным деструктором, если базовый класс является QObject/QWidget.Я просто решил сделать по аналогии, в одной из программ. которая падает при закрытии. И программа перестала падать. Как это работает я не пойму. Если я правильно понимаю, то должно работать так. Дано: где-то далее в коде: в выделенной строке должен вызываться деструктор класса MyObjectили я не прав? |
|
|
BRE |
![]()
Сообщение
#4
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Прав.
Вызовется деструтор MyObject, а потом QObject. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#5
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
и ещё, при отладке в Креаторе увидел что в консоль приложения печатается такая строка:
если же запускаю программу в командной строке виндовоза, то такой надписи нет. Это может предвещать что-то плохое? |
|
|
Алексей1153 |
![]()
Сообщение
#6
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
Litkevich Yuriy, а когда запущено на отладку без точек останова - не видно, где падение произошло ? Обычно стек вызовов можно раскрутить до своего кода
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#7
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Обычно стек вызовов можно раскрутить до своего кода да вот GDB сволочной отладчик, когда нужно найти проблему, он руками разводит, говорит "Может стек корупт, а?"Но походу тут лажа очередная с qmake'ом. Прибил всю сборку, собрал начисто, всё работает. Даже намёка на падение нет, что без деструктора, что с явно созданным. |
|
|
DEADHUNT |
![]()
Сообщение
#8
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 430 Регистрация: 15.4.2009 Пользователь №: 686 Спасибо сказали: 26 раз(а) Репутация: ![]() ![]() ![]() |
добавляя виртуальный деструктор получаем:
1) полиморфный класс, т.е. возможность использования dynamic_cast, typeid, ... 2) объекты можно удалять через указатель на базовый класс, при этом будет вызываться деструктор производного класса и корректно свобождается память. |
|
|
Влад |
![]()
Сообщение
#9
|
Участник ![]() ![]() Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: ![]() ![]() ![]() |
Ежли мой склероз мне не изменяет, еще Джефф Элджер в своей "С++ Библиотека программиста" советовал: делайте деструктор всегда виртуальным, за исключением лишь тех случаев, когда есть чрезвычайно веские основания поступить иначе.
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#10
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
DEADHUNT |
![]()
Сообщение
#11
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 430 Регистрация: 15.4.2009 Пользователь №: 686 Спасибо сказали: 26 раз(а) Репутация: ![]() ![]() ![]() |
речь идёт о деструкторе базового класса или наследника?
класс имеет виртуальный деструктор, т.е. в классе есть хотя бы один виртуальный метод, таким образом компилятор считает данный класс полиморфным, и обращается с ним иначе чем с обычными классами(как описано выше). |
|
|
Алексей1153 |
![]()
Сообщение
#12
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#13
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
класс имеет виртуальный деструктор ну это-то понятно, это я в первых постах написал.Мне не понятно, может ли влиять явное создание пустого деструктора у наследника QObject (или иного класса, с виртуальным деструктором). На мой взгляд нет. Но похоже это какая-то кривость Креатора. Любое изменение в коде (в заголовочниках) сейчас опять выливается в аврию. Если же компилю в консоли или в PN-2, то всё нормально. |
|
|
kwisp |
![]()
Сообщение
#14
|
![]() астарожна ынтжинэр ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
лишний повод(причина) не использовать креатор.
|
|
|
Iron Bug |
![]()
Сообщение
#15
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Мне не понятно, может ли влиять явное создание пустого деструктора у наследника QObject (или иного класса, с виртуальным деструктором). На мой взгляд нет. однозначно нет. скорее всего, ошибка в потоках, либо в оставшихся "висящими" объектах ядра. проверяй, все ли ресурсы освобождаются корректно, правильно ли завершаются потоки, нет ли "подвисших" линков на несуществующие переменные после закрытия основного потока. |
|
|
Алексей1153 |
![]()
Сообщение
#16
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
и ещё
... вызываются ли виртуальные функции в деструкторе (низя) ... производится ли где-то явное приведение типа с последующим изменением начала объекта (бьётся таблица виртуальных функций) |
|
|
BRE |
![]()
Сообщение
#17
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
kwisp |
![]()
Сообщение
#18
|
![]() астарожна ынтжинэр ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
BRE,
не знаю почему но могу предположить: при вызове вирт. диструктора вызывается на самом деле деструктор производного объекта(уничтожает поля производного класса) , который в свою очередь вызывает деструктор базового класса(тот самый виртуальный) ав нем виртуальные функции которые могут использовать уже удаленные поля производного класса... по моему логично если диструктор не виртуальный а в нем виртуальные функции то эти вирту функции напросто обратятся уже к удаленным полям производного объекта. порядок вызова деструкторов обратный то |
|
|
Алексей1153 |
![]()
Сообщение
#19
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
Вроде нельзя, потому что виртуальная таблица уже порушена. Будут вызываться функции данного объекта, а не потомков
А как там в стандарте ? Надо будет эксперимент поставить, но щас у меня мысль в другом русле, пока не могу ) Сообщение отредактировал Алексей1153 - 17.8.2010, 19:13 |
|
|
BRE |
![]()
Сообщение
#20
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
На сколько я помню, при удалении объекта с виртуальным деструктором, будет вызван деструктор из его vtbl. После его отработки, vtbl будет переключена на таблицу базового класса и будет вызван его деструктор и т.д. Даже если ты будешь удалять объект по указателю на его базовый класс. В этом и смысл.
А вот с конструкторами такое не пройдет, они не могут быть виртуальными. Поэтому, в конструкторе будет вызван виртуальный метод того класса, конструктор которого в данный момент работает, даже если в производном классе он переопределен. |
|
|
Алексей1153 |
![]()
Сообщение
#21
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
нет, речь не про виртуальный деструктор, а про явный вызов виртуальных функций из деструктора предка
|
|
|
BRE |
![]()
Сообщение
#22
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Ты про чисто виртуальные функции или просто виртуальные?
|
|
|
Алексей1153 |
![]()
Сообщение
#23
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
Щас сделаю тест, самому охота вспомнить )
хм, выяснилась интересная вещь. Ни Креатор, ни Студия (№6, №9) просто не позволяют так сделать ещё на уровне линковки
Цитата unresolved external symbol "public: virtual void __thiscall A::F(void)" (?F@A@@UAEXXZ) Цитата undefined reference to `A::F()' А ведь я помню, нарвался как то на подобное, но не могу вспомнить, как именно Сообщение отредактировал Алексей1153 - 17.8.2010, 19:54 |
|
|
Iron Bug |
![]()
Сообщение
#24
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
На сколько я помню, при удалении объекта с виртуальным деструктором, будет вызван деструктор из его vtbl. После его отработки, vtbl будет переключена на таблицу базового класса и будет вызван его деструктор и т.д. Даже если ты будешь удалять объект по указателю на его базовый класс. В этом и смысл. А вот с конструкторами такое не пройдет, они не могут быть виртуальными. Поэтому, в конструкторе будет вызван виртуальный метод того класса, конструктор которого в данный момент работает, даже если в производном классе он переопределен. абсолютно верно. именно так и будет. если в классе виртуальная функция определена, то она может быть вызвана в деструкторе этого класса и в деструкторах классов-наследников, если вдруг потребуется. для каждого класса могут использоваться его функции и функции прародителей. для деструктора нет ограничений. они есть только для конструктора - так как в момент создания элемента виртуальной таблицы и указателя this просто ещё нет. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#25
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
... вызываются ли виртуальные функции в деструкторе (низя) нет, у меня именно пустой деструктор (мне нечего было подчищать при завершении работы класса), а насчёт того, что нельзя, я тоже краем уха где-то слышал.... производится ли где-то явное приведение типа с последующим изменением начала объекта вот это не понял, что значит с изменением начала объекта?
|
|
|
Алексей1153 |
![]()
Сообщение
#26
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
а насчёт того, что нельзя, я тоже краем уха где-то слышал. поскольку точно не могу факт привести, не буду придумывать ![]() вот это не понял, что значит с изменением начала объекта? например Раскрывающийся текст
Сообщение отредактировал Алексей1153 - 18.8.2010, 6:52 |
|
|
kwisp |
![]()
Сообщение
#27
|
![]() астарожна ынтжинэр ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
хм, выяснилась интересная вещь. Ни Креатор, ни Студия (№6, №9) просто не позволяют так сделать ещё на уровне линковки ты в первом посте верно написал - при вызове виртуальных функций из деструктора - просто напросто вызовутся функции того класса чей деструктор а не предков. что стандарт по этому поводу говорит конечно интересно. а не линкуется, потому что получается вызов чисто виртуальной функции. Раскрывающийся текст
|
|
|
Алексей1153 |
![]()
Сообщение
#28
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
функции данного объекта, а не потомков kwisp, вообще-то, я про потомков говорил ) Ведь назначение виртуальных функций - вызывать методы потомков вызов чисто виртуальной функции. такой вызов не запрещён вроде ![]() Потому что абстрактный объект создать нельзя, а потомки должны обязательно переопределить виртуалки Сообщение отредактировал Алексей1153 - 18.8.2010, 10:13 |
|
|
kwisp |
![]()
Сообщение
#29
|
![]() астарожна ынтжинэр ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Алексей1153 |
![]()
Сообщение
#30
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
что тут верить то
![]()
Сообщение отредактировал Алексей1153 - 18.8.2010, 12:22 |
|
|
kwisp |
![]()
Сообщение
#31
|
![]() астарожна ынтжинэр ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Алексей1153,
хитрец ты вызываешь не чисто виртуальную функцию а переорпеделенную. рассмотри пример у меня в посте выше и вывод на консоль. |
|
|
DEADHUNT |
![]()
Сообщение
#32
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 430 Регистрация: 15.4.2009 Пользователь №: 686 Спасибо сказали: 26 раз(а) Репутация: ![]() ![]() ![]() |
что тут верить то ![]() код собирается без ошибок. а в конце 10.4 (Abstract Classes) написано: Цитата Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined. в таких случаях лучше реализовывать чисто виртуальную функцию:
|
|
|
Алексей1153 |
![]()
Сообщение
#33
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
хитрец ты вызываешь не чисто виртуальную функцию а переорпеделенную. прошагай отладчиком - никакой хитрости ![]() ![]() Сообщение отредактировал Алексей1153 - 18.8.2010, 13:58 |
|
|
DEADHUNT |
![]()
Сообщение
#34
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 430 Регистрация: 15.4.2009 Пользователь №: 686 Спасибо сказали: 26 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Iron Bug |
![]()
Сообщение
#35
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Может кто-нибудь объяснить, как может влиять создание руками виртуального деструктора, при условии, что его тело пустое? я уже писала: никак не влияет. просто лишний вызов или перераспределение кода при очередной компиляции скрывает ошибку потоков или затирания памяти. от пустого деструктора абсолютно ничего не прибавляется, виртуальный он или не виртуальный. |
|
|
Алексей1153 |
![]()
Сообщение
#36
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
DEADHUNT, понятно )
А я то понял, что про именно из A вызов говорилось Сообщение отредактировал Алексей1153 - 18.8.2010, 19:13 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#37
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
вобщем шутки RunTime продолжаются.
Похоже, что чуваки утверждавшие, что qmake - для простеньких приложений, правы. И видимо я дорос до более сложного приложения. Прога падает при некоторых изменениях в исходнике. падает в самых неожиданных местах. Попытка добавить qDebug в выше стоящие по иерархии модули решает проблему (т.к. эти модули перекомпилируются). Проделал такой эксперимент. При возникновении проблем, в один из вышестоящих модулей добавляю пустую строку - это вызывает перекомпиляцию. И теперь прога работает стабильно. Не уж-то на CMake придётся переходить? Так не охота что-то изучать на середине проекта. |
|
|
Алексей1153 |
![]()
Сообщение
#38
|
![]() фрилансер ![]() ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2943 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: ![]() ![]() ![]() |
Litkevich Yuriy, а у тебя нигде директива не используется такая?
#pragma pack upd (всё, вопрос неактуален )) Внимательнее прочитал пост Юрия и понял, что это ни при чём) Сообщение отредактировал Алексей1153 - 19.8.2010, 12:44 |
|
|
DEADHUNT |
![]()
Сообщение
#39
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 430 Регистрация: 15.4.2009 Пользователь №: 686 Спасибо сказали: 26 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
BRE |
![]()
Сообщение
#40
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
DEADHUNT |
![]()
Сообщение
#41
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 430 Регистрация: 15.4.2009 Пользователь №: 686 Спасибо сказали: 26 раз(а) Репутация: ![]() ![]() ![]() |
вот нашёл пример: http://www.devexp.ru/2010/01/cmake-i-qt/ там макросы для этого есть.
на самом деле зачем постоянно использовать qmake, ведь проект который использует Qt != Qt проект. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#42
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 24.5.2025, 11:16 |