LINUX.ORG.RU

Сравнение: MFC vs Qt


0

0

Вышел перевод Andi Peredri, автор статьи Pascal Audoux. Статья не претендует на полноту охвата сравнения, но достаточно точно подмечены некоторые особенности работы с обеими библиотеками. Надеемся, что это первый перевод из серии ... vs Qt.

>>> Перевод можно прочесть здесь:

Ответ на: комментарий от anonymous

>ANSI :) char -- это минимальная единица адресации. Есть архитектуры (вроде MIPS) где char=4 байта.

Там минимальная единица адресации 4 байта ;)

А с точки зрения C (С89)это вроде бы символьный тип к адресации прямого отношения
не имеющий ImHO тут налицо терминологическая путаница потому как тогда какого размера должен быть wchar_t ?

BTW:
cat /usr/src/linux/include/asm-mips/types.h | grep s8
typedef __signed__ char __s8;
typedef __signed char s8;

то же самое с mips64

>И вообще, в C определяются только минимальные размеры типов. Типа char <= short <= int <= long <= long long char >= 8 бит short >= 16 бит int >= 16 бит long >=
>32 бит long long >= 64 бит

ДА в C определены минимальные размеры - сие верно но вот к char это вроде бы
не должно относится

sS ★★★★★
()

А что такое MFC? Что-то от M$?

bormann
()
Ответ на: комментарий от sS

>А с точки зрения C (С89)это вроде бы символьный тип к адресации >прямого отношения >не имеющий ImHO тут налицо терминологическая путаница потому как >тогда какого размера должен быть wchar_t ?

В C89 для многих функций типа memcpy использовался char* Да и нельзя использовать char как символьный тип, если мы не можем адресовать его. Соответственно размер char выбирается так, чтобы он совпадал с минимальной единицей адресации.

Если я не ошибаюсь, то для MIPS sizeof (wchar_t) == sizeof (char)

Насколько я помню для char там определено >=8bit. Все-таки C -- это ассемблер.

anonymous
()

qrot:

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

Давай тогда разделим эти два случая:

1. В конструкторе не выбрасывается исключения при ошибке.

Отстойная реализация библиотеки - переработать, чтобы выбрасывалось :).

2. В конструкторе выбрасывается исключение.

Только так. Исключение - единственный (и достаточный) способ сообщения об ошибке из конструктора. При создании окна перехватывать и реагировать.

Какие проблемы?

hbee ★★★★
()
Ответ на: комментарий от hbee

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

пока я делаю так( что етесственно не кактит при реальной работе): в qtdesigner рисую, накидываю slots signals потом компилю раз, вытягиваю реальные h&cpp файлы - и с ними дальше. блин, а если я гуи еще захотел поправить??..

зы в линухе программингу тока учусь..пользоваться вроде как что-то умею, дома от виндов без проблем отказался вот уже как полгода.

oav
()
Ответ на: комментарий от ANDI

QT вообще ничего не хранит. Как хранить описанные в коде строковые константы, определяет компилятор. И по умолчанию это ASCII.

Eugene_Korobko
()

2hbee: гм.. ну а на вызов деструктора в случае исключения в конструкторе, мы что, хер положим?

qrot
()

2bormann: да! это Microsoft Fortran Compler! :)) по крайней мере именно это пришло мне в голову когда я впервые увидел эту аббревиатуру при инсталляции ваткома.. эхх, давно это было все...

qrot
()

2oav
> бъянишь может qtdesigner и эта непонятная идея с .h.ui файлы? они
> считают что в классе под диалогом только обработчики событий
> бывают? 
>
> пока я делаю так( что етесственно не кактит при реальной работе):
> в qtdesigner рисую, накидываю slots signals потом компилю раз, 
> вытягиваю реальные h&cpp файлы - и с ними дальше. блин, а если я
> гуи еще захотел поправить??..

Дурная голова, другим частям тела покою нет. Ты uic использовать
пробовал ? А документацию хорошо читал ?

2ogr:
> - А когда речь зашла про QString, то автор чего-то "забыл" про
> CString
Ты подонок сам хоть статью то читал ? 

anonymous
()
Ответ на: комментарий от qrot

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

window *w = desktop()->create_window(....);
if(w)
{
    window *nw = w->create_window(...);
    ....
}

и исключения не нужны. Проблему вызова деструктора можно решить или обработкой WM_CLOSE или оберткой типа auto_ptr;

anonymous
()

qrot:

>ну а на вызов деструктора в случае исключения в конструкторе, мы что, хер положим?

Нет, Страуса откроем :)))

"Объект не считается созданным до тех пор, пока не завершится выполнение его конструктора".

hbee ★★★★
()

Да, std::auto_ptr классная вещь. Всегда ею пользуюсь.

hbee ★★★★
()

Про двухшаговую инициализацию. Проблема следующая: из конструкторов нельзя вызывать виртуальные функции. Поэтому потомок не может переопределить никакие параметры создания. Передавать их через параметры конструктора громоздко и неудобно. Обычно эта проблема обходится так: class base { public: inline base(){init();}; protected: virtual void init(); class not_used{}; base(not_used*){}; };

class super:public base { public: inline super():base(static_cast<not_used*>(0)){init();}; protected: virtual init(); super(not_used){}; };

Есть, конечно, проблемы со статически создаваемыми (без new) полями сложных типов, но по сути, эта та же двухшаговая инициализация. В MFC это просто видно. Как подобное сделано в QT я не знаю. Вероятно, через rtti. Но я лучше буду видеть, что происходит.

Eugene_Korobko
()
Ответ на: комментарий от anonymous


>В C89 для многих функций типа memcpy использовался char* Да и нельзя использовать char как символьный тип, если мы не можем адресовать его.
>Соответственно размер char выбирается так, чтобы он совпадал с минимальной единицей адресации.
>Если я не ошибаюсь, то для MIPS sizeof (wchar_t) == sizeof (char)
>Насколько я помню для char там определено >=8bit. Все-таки C -- это ассемблер.

Ну если C рассматривать как навороченный НО макроассемблер то наверное так и есть :)

Вот только не совсем понятно тогда насчет переносимости двоичных данных
Неужели все приходится таскать через XDR ?

sS ★★★★★
()

А вообще, чем меньше нестандартных приёмов вроде каких-то собственных прекомпиляторов, собственного rtti и прочего Г., тем лучше. Кстати тут я пишу на QT 2.3, и понадобилось в качестве заглушки испольовать клиента ftp. В QT я подходящего класса не нашел и решил использовать MFC - CFtpConnection. Но обломился. Поскольку и MFC и QT переопределяют CRT, отчего использовать иъ вместе нельзя. И вообще, С++ такой мощный язык, неужели его мало???

Eugene_Korobko
()

2 qrot:

Всё там же. Подробно расписано. Я прям удивляюсь... Цитировать здесь или сам прочитаешь? Интересная книга (3rd edition) сама по себе, кстати. Как "Три мушкетера" :)))

hbee ★★★★
()

2hbee: а, ты все таки это прочитал прежде, чем я удалил :))

qrot
()

А здесь можно редактировать? Или ты админ? ;)

hbee ★★★★
()
Ответ на: комментарий от sS

>Вот только не совсем понятно тогда насчет переносимости >двоичных данных >Неужели все приходится таскать через XDR ?

Да. Переносимость двоичных данных между разными архитектурами -- штука странная.

anonymous
()
Ответ на: комментарий от sS

В том и дело, что ни в каком стандарте не специфицирован размер char-а. И sizeof выдаёт значение в количестве char-ов, а не байтов. Такая вот фигня... Это называется "портабельный" язык Цэ.

Antichrist
()
Ответ на: комментарий от sS

Цэ никоим образом не помогает организовать портабельность бинарных данных. По этой причине читать/писать надо побайтно (забив на оверхед), а в некоторых случаях и битовыми потоками. Иначе никак. Я по этому поводу уже много матерных слов с примерами кода тут и в ФИДО понаписал...

Antichrist
()
Ответ на: комментарий от Antichrist

>Цэ никоим образом не помогает организовать портабельность бинарных данных. По этой причине читать/писать надо побайтно (забив на оверхед), а в
>некоторых случаях и битовыми потоками. Иначе никак. Я по этому поводу уже много матерных слов с примерами кода тут и в ФИДО понаписал...

Schildt говорит что в sizeof возвращает длину в БАЙТАХ - либо у меня левый перевод либо корифей
не в курсе :)

PS: Нечто в MIPS-ах нет никакого корректного средства упаковки чаров ?
Я чесно говоря поледний MIPS мельком трогал лет 5 назад (под IRIX 5.не помню скоко)
И как то даже не задумывался что там такие крупные чары :)

sS ★★★★★
()
Ответ на: комментарий от anonymous

anonymous (*) (2002-08-29 10:47:07.258):

>> "- MSDN доступна бесплатно по адресу msdn.mictosoft.com (так что
>> платить не обязательно) "

> MSDN Library -> buy it first baby :-)

Лежит она открыто, чё гнать-то?
http://msdn.microsoft.com/library/


<OFFTOPIC>
Посмотрите какой самолёт "красивый":
http://www.airliners.net/open.file/215269/M/ :)
</OFFTOPIC>

Dimentiy ★★
()

2hbee: можно удалить сообщение - см линки над сообщениями
смартпоинтеры конечно в некоторой степени решают проблему.. но они не
удобны, если нужно просто выделить кусок памяти, кроме того - MFС уже
было когда еще ни о каких смартпоинерах речи не шло.

qrot
()
Ответ на: комментарий от Dimentiy


><OFFTOPIC>
>Посмотрите какой самолёт "красивый":
>http://www.airliners.net/open.file/215269/M/ :)
></OFFTOPIC>

Туполев был прав - "Некрасивые самолеты не летают" :)


Remark
Photographer F-BASX Aircraft was broken up at this location soon

Вот если бы так еще с ПО было ...





sS ★★★★★
()

2gregbg (*) (2002-08-29 12:33:05.788):"logINу, сразу видно, что ты на GTK+ не писал, там это по-другому выглядит ;)"

Теперь посмотри на кол-во оберток. (((X11)GTK)GTK+) и сравним QT: ((X11)QT) разница есть?

2oav (*) (2002-08-29 12:20:46.513): "По поводу Windows Forms - это не обертка "на кривой Win32 API" а обсолютно новая, в идеале кроссплатформенная библиотека, часть .NET Framefork. .. WIN32API и dotNET - эта РАЗНЫЕ ПЛАТФОРМЫ, господа, ну не надо писать глупостей, даже не узнав что это и зачем."

Вай-вай. Гон то какой. Ты хоть сам понимаешь что сказал? Ты так думаешь, что .NET не базируется на pure-WinAPI? Серьезно? А на чем оно базируется? А? int $0x10? ;-)

"объянишь может qtdesigner и эта непонятная идея с .h.ui файлы? они считают что в классе под диалогом только обработчики событий бывают?
пока я делаю так( что етесственно не кактит при реальной работе): в qtdesigner рисую, накидываю slots signals потом компилю раз, вытягиваю реальные h&cpp файлы - и с ними дальше. блин, а если я гуи еще захотел поправить??"

Тыб лучше не спорил, а умных дядей слушал. .ui файлы очень полезная вещь. Просто у тебя не хватило знаний/терпения/сил/опыта понять как с ними работать.

_Не нужно_ редактировать .h .cpp файлы, которые были получены из .ui (uic компилиром). Делаеться куда проще. Создаешь свой класс, который являеться дочерним от того класса, который ты создал в qtdesigner.

class MyClass : public MyClassFromQTDesigner
{};
А в этом классе меняешь все что душе угодно, причем если ты захочешь что-то изменить в .ui файле, то просто перекомпилируй его, и все будет работать как прежде.

Теперь видно, почему .ui - это так хорошо? ;-))

logIN
()

не надо писдеть про мипс - там чар 1 байт и sizeof всегда все в байтах вываливает, иначе б вы заколебались кроссплатформенные вещи писать. у меня вот тут есть сорсы проги которая интенсивно с байтовым потоком работает и портирована на полсотни платформ, так вот там никогда проблем с реальным размером char не возникало. что касается мипсов, вот кусок:
localhost> uname -a
ULTRIX localhost 4.3 1 RISC
localhost> grep CHAR /usr/include/limits.h
#define CHAR_BIT 9 /* # of bits in a "char" */
#define CHAR_BIT 8 /* # of bits in a "char" */
#define CHAR_MIN (-128) /* min integer value of a "char" */
#define CHAR_MAX 127 /* max integer value of a "char" */
#define UCHAR_MAX 255
#define SCHAR_MIN CHAR_MIN /* ANSI signed "char" min */
#define SCHAR_MAX CHAR_MAX /* ANSI signed "char" max */
#define CHAR_MAX 255 /* max integer value of a "char" */
#define CHAR_MIN 0 /* min integer value of a "char" */
#define MAX_CHAR 256 /* max # of bytes in term canon input line (X/OPEN) */

anonymous
()

hbee

а в WTL не двушаговая? умник, мля :(

anonymous
()

http://www.codenet.ru/progr/cpp/2/gl1.php#gl1.3
"Переменная типа char имеет размер, естественный для хранения символа на данной машине (обычно, байт), а переменная типа int имеет размер, соответствующий целой арифметике на данной машине (обычно, слово). Диапазон целых чисел, которые могут быть представлены типом, зависит от его размера. В C++ размеры измеряются в единицах размера данных типа char, поэтому char по определению имеет размер единица. Соотношение между основными типами можно записать так:

1 = sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
sizeof(float) <= sizeof(double)

В целом, предполагать что-либо еще относительно основных типов неразумно."

А вот в 
http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/n843.htm
JTC1/SC22/WG14 N843 
Programming languages  --  C
6.5.3.4  The sizeof operator
[#2] The sizeof operator yields the size (in bytes)  of  its operand.
[#3] When applied to an operand that has type char, unsigned char,  or  signed char, (or a qualified version thereof) the result is 1.

anonymous
()

Texas Instruments TMS-320 (DSP)

sizeof(char) = 1

А на самом деле 16 бит.
Ну не умеет он работать с байтами. Только можно эмулировать через битовые поля.

alman ★★★
()
Ответ на: комментарий от Dimentiy

2 Dimentiy (*) (2002-08-29 20:10:50.536) :

> MSDN Library -> buy it first baby :-)

"Лежит она открыто, чё гнать-то?
http://msdn.microsoft.com/library/";

If so, try to download it :)))

It is for MSDN subscribers only and you must buy it first, stupid. MSDN Library is not only DOX, but -> many examples
and LIBRARIES.

WBR
The Int

anonymous
()

anonymous (*) (2002-08-30 11:11:41.111)
все примеры из мсдн доступны онлайн для любого у кого есть инет. все библиотеки, доки, примеры по Win32 API есть в Platform SDK, который распространятеся бесплатно и доступен для загрузки целиком и по частям любому кто пожелает. короче - руки прочь от нашей самой любимой конторы!

qrot
()
Ответ на: комментарий от logIN

Вай-вай. Гон то какой. Ты хоть сам понимаешь что сказал? Ты так думаешь, что .NET не базируется на pure-WinAPI? Серьезно? А на чем оно базируется? А? int $0x10? ;-) Перед тем как писать, подумай о чем ты пишешь ;)) Естесственно, внутри в реализации под Win она исползует Win32API. Но это реализация framework под Win, программист работает с framework и Win32 API не использует. ;) Под линух реализация будет другой, программа таже. (в идеяле естессна, к сожалению, в ближ. будущем это ожидать не стоит :-( )

_Не нужно_ редактировать .h .cpp файлы, которые были получены из .ui (uic компилиром). Делаеться куда проще. Создаешь свой класс, который являеться дочерним от того класса, который ты создал в qtdesigner.

как раз вчера об этом узнал. полностью согласен что удобно и логично. единсвенное что не очень нравится, это еще 2 файла (h & cpp) на gui, но это мелочи

oav
()

Antichrist: идешь в su.c-c++, задаешь вопрос, обязан ли быть char однобайтовым, получаешь ответ и больше не ругаешься словами, которые применимы к тебе в первую очередь.

hbee: ты что-то про проблему использования виртуальных функций в конструкторе и деструкторе слышал? О том, из какого класса будет вызвана функция в его конструкторе и почему это решение принципиально? И какие последствия имело противоположное решение в Object Pascal? Про твое полное незнание истории я молчу - MFC не была придумана M$'ом, она была куплена под именем AFX и переименована.

В MFC во многих случаях можно обойтись без двухшаговой инициализации. А то, что конструктор без параметров используется при построении объекта из потока - очень грамотное решение в этих условиях.

patologoanatom

anonymous
()

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

Eugene_Korobko
()

>ты что-то про проблему использования виртуальных функций в конструкторе и деструкторе слышал? О том, из какого класса будет вызвана функция в его конструкторе и почему это решение принципиально? И какие последствия имело противоположное решение в Object Pascal?

Нет, не слышал, не знаю.

>Про твое полное незнание истории я молчу - MFC не была придумана M$'ом, она была куплена под именем AFX и переименована.

И этого факта не знал.

В общем, посыпаю голову пеплом. Буду читать :).

hbee ★★★★
()

И всё равно QT мне больше нравится :)))

hbee ★★★★
()
Ответ на: комментарий от anonymous

К этим бздливым ламерам? Не фиг. Они в драфт стандарта плюсов посмотрят, а про ANSI C как всегда забудут.

Antichrist
()

2 hbee: Краткое описание проблемы вызова виртуальной функции из конструктора. class A { public: A(){f();}; virtual void f(){}; };

class B:public class A { public: B():A(){}; virtual void f(){}; };

Так вот, в B::B() вызовется A::f, а не B::f. Это происходит потому, что объект класса B считается принадлежащим этому классу после { его конструктора. Вызов конструктора предка находится до этого символа, поэтому внутри A::A объект ещё не принадлежит классу B, а принадлежит классу А, поэтому вызывается A::f(). Это приводит к проблеме: невозможно полиморфное поведение при конструировании. Особо остро это чувствуется, когда конструктор сложен (как в случае оконных классов). Возможное решение я уже приводил в данной флейме.

Eugene_Korobko
()
Ответ на: комментарий от anonymous

> If so, try to download it :)))
>
> It is for MSDN subscribers only and you must buy it first, stupid.
> MSDN Library is not only DOX, but -> many examples
> and LIBRARIES.

Не совсем так. Скорее, в MSDN Subscription помимо собственно Library входит ещё много чего.
Хотя в целом думаю это спор ни о чём, вопрос всего лишь в терминах.

stupid-ом ты меня зря назвал правда, впрочем чего ещё на лоре ждать. Прощён.

p.s. Мне похуй вообще-то, на полке коробка с кучей DVD-шек от MS лежит :)

Dimentiy ★★
()

"Полиморфное поведение при конструировании" звучит довольно подозрительно. Ведь для чего нужны виртуальные функции? Для вызова функции объекта неизвестного типа. А при конструировании в C++ тип всегда точно известен - иначе никак.

Так может, вызов виртуальных функций в конструкторе - изврат, одна из многочисленных засад в C++, которых надо просто избегать?

hbee ★★★★
()

2hbee (*) (2002-08-30 19:39:08.566):

> Так может, вызов виртуальных функций в конструкторе - изврат,
> одна из многочисленных засад в C++, которых надо просто избегать?

Язык этот надо избегать. ;-)

badger
()

2 badger: "C++ makes it harder to shoot yourself in the foot, but if you do, it will blow your entire foot off". Bjarne Stroustrup. Мораль - надо иметь голову на плечах и прочитать Effective C++ Скотта Майерса хотя бы раза три.

anonymous
()

2anonymous (*) (2002-08-31 09:50:17.172):

> "C++ makes it harder to shoot yourself in the foot, but if you
> do, it will blow your entire foot off". Bjarne Stroustrup.
> Мораль - надо иметь голову на плечах и прочитать
> Effective C++ Скотта Майерса хотя бы раза три.

Надо иметь голову на плечах, а не тупо цитировать Страуструпа.
Ты бы ещё библию процитировал. Получилось бы настолько же убедительно.
;-)

badger
()

char type inISO/IEC 9899:1999(E)

An object declared as type char is large enough to store any member of the basic execution character set. If a member of the basic execution character set is stored in a char object, its value is guaranteed to be positive. If any other character is stored in a char object, the resulting value is implementation-defined but shall be within the range of values that can be represented in that type.

anonymous
()

char type in ISO/IEC 9899:1999(E)

The rank of long long int shall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.

The rank of char shall equal the rank of signed char and unsigned char.

А про какие-то размеры целых типов в стадарте C, как впрочем и C++, нигде не сказано.

anonymous
()

2 badger (*) (2002-08-31 20:17:33.43) >Надо иметь голову на плечах, а не тупо цитировать Страуструпа.

Ну да, кидать голословные утверждения, насчет какие языки избегать (даже без указания к какому же все таки языку стремиться) несомненно верх интеллекта.

rGlory

anonymous
()

2anonymous (*) (2002-09-01 08:49:47.83):

> Ну да, кидать голословные утверждения, насчет какие
> языки избегать (даже без указания к какому же все таки языку
> стремиться) несомненно верх интеллекта.

Батенька анонимус, я не кидал голословные утверждения.Я всего лишь
иронично ответил на письмо, в котором было сказано, что надо
избегать многочисленных засад C++.Поскольку столько засад,так может
быть от языка-то и убежать?

badger
()

Прочитайте Голуба "С и С++ - правила программирования" и большинство "засад" окажутся надуманными. Удивительно высокий КПД у книги.

anonymous
()

Присоединяюсь насчёт Голуба - отличная книга. Ещё неплохо изучить Элджера, "C++ for real programmers". Ну, а дядю Бьярни знать наизусть ;). И ещё - Рихтера, по программированию для Windows. Это одна из редких книг, где операционная система и язык программирования, на базе которых излагается - абсолютно не важны по сравнению с идеями.

На самом деле потенциально опасных мест в C++ немного, и большинство из них происходят от совместимости с C (от которой будут постепенно избавляться). Если нормально проектировать, не пользоваться низкоуровневыми и подозрительными с точки зрения логики возможностями - ловушки куда-то денутся :). Мощный инструмент требует осторожного обращения ;).

Антихрист, молчать! :))) Я в курсе недостатков C++ с точки зрения академической завершенности и закругленности. Может быть, со временем все перейдут на OCaml, но нескоро.

hbee ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.