Працюючи над вбудованим проектом, я спробував один раз попрацювати у всіх C, і просто не витримав. Це було настільки багатослівно, що ускладнювало щось читання. Крім того, мені сподобались написані мною оптимізовані для вбудованих контейнери, які повинні були стати набагато менш безпечними та складнішими для виправлення #defineблоків.
Код, який у C ++ виглядав так:
if(uart[0]->Send(pktQueue.Top(), sizeof(Packet)))
pktQueue.Dequeue(1);
перетворюється на:
if(UART_uchar_SendBlock(uart[0], Queue_Packet_Top(pktQueue), sizeof(Packet)))
Queue_Packet_Dequeue(pktQueue, 1)
що багато людей, мабуть, скажуть, що це нормально, але стає смішним, якщо вам доводиться робити більше, ніж кілька викликів "методу" в рядку. Два рядки C ++ перетворюються на п'ять C (через обмеження довжини рядка 80 символів). Обидва вони генерують однаковий код, тому це не так, як цільовий процесор дбав!
Одного разу (ще в 1995 році) я спробував написати багато C для багатопроцесорної програми обробки даних. Вигляд, коли кожен процесор має власну пам’ять і програму. Постачальник постачав компілятором компілятор C (якийсь похідний HighC), їх бібліотеки були закритими, тому я не міг використовувати GCC для побудови, а їх API були розроблені з урахуванням того, що ваші програми в першу чергу будуть ініціалізацією / процесом / термінантний різновид, тому міжпроцесорний зв’язок був у кращому випадку елементарним.
Я отримав приблизно місяць, перш ніж відмовитись, знайшов копію cfront і зламав її у файли make-файлів, щоб я міг користуватися C ++. Cfront навіть не підтримував шаблони, але код С ++ був набагато, набагато зрозумілішим.
Загальні, безпечні для типу структури даних (із використанням шаблонів).
Найближче до шаблонів - це оголошення файлу заголовка з великою кількістю коду, який виглядає так:
TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{ }
потім витягніть його з чимось на зразок
#define TYPE Packet
#include "Queue.h"
#undef TYPE
Зверніть увагу, що це не буде працювати для складних типів (наприклад, без черг unsigned char), якщо ви не зробите typedefперший.
О, і пам’ятайте, якщо цей код насправді ніде не використовується, то ви навіть не знаєте, чи він синтаксично правильний.
EDIT: Ще одне: вам потрібно буде вручну керувати створенням екземпляра коду. Якщо ваш код "шаблону" не всі вбудовані функції, то вам доведеться ввести певний контроль, щоб переконатися, що все запускається лише один раз, щоб ваш компонувальник не виплюнув купу помилок "декількох екземплярів Foo" .
Для цього вам доведеться помістити невбудований матеріал у розділ «реалізація» у вашому заголовковому файлі:
#ifdef implementation_##TYPE
#endif
А потім, в одному місці у всьому коді на варіант шаблону , потрібно:
#define TYPE Packet
#define implementation_Packet
#include "Queue.h"
#undef TYPE
Крім того, цей розділ реалізації повинен знаходитись поза межами стандартної #ifndef/ #define/ #endifектенії, оскільки ви можете включити файл заголовка шаблону в інший файл заголовка, але пізніше потрібно створити екземпляр у .cфайлі.
Так, це стає негарно швидко. Ось чому більшість програмістів на С навіть не намагаються.
RAII.
Особливо у функціях з кількома точками повернення, наприклад, не потрібно пам’ятати про звільнення мьютексу в кожній точці повернення.
Ну, забудьте свій гарний код і звикніть, що всі ваші точки повернення (крім кінця функції) становлять gotos:
TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{
TYPE * result;
Mutex_Lock(this->lock);
if(this->head == this->tail)
{
result = 0;
goto Queue_##TYPE##_Top_exit:;
}
Queue_##TYPE##_Top_exit:
Mutex_Lock(this->lock);
return result;
}
Деструктори загалом.
Тобто ви один раз пишете d'tor для MyClass, тоді, якщо екземпляр MyClass є членом MyOtherClass, MyOtherClass не повинен явно деініціалізувати екземпляр MyClass - його d'tor викликається автоматично.
Побудова об'єкта повинна явно оброблятися однаково.
Простори імен.
Це насправді просто, щоб виправити: просто прикріпіть префікс до кожного символу. Це основна причина роздуття джерела, про яку я вже говорив раніше (оскільки класи - це неявні простори імен). Люди С живуть цим, ну, вічно, і, мабуть, не побачать, у чому велика справа.
YMMV