Re[24]: JetBrains
От: so5team https://stiffstream.com
Дата: 18.04.16 20:53
Оценка:
Здравствуйте, mgu, Вы писали:

mgu>Спасибо за полезную ссылку, но вот что меня беспокоит: при вашей политике распространения библиотеки в виде исходного кода, как бедные пользователи будут угадывать правильный компилятор?


Гораздо важнее другой вопрос: когда библиотека поставляется в бинарном виде, как быть тогда? На ваш же вопрос ответ прост: поддержка С++11.

mng>И что им делать, если их текущий сборщик не переварит всех нововведений?


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

S>>Так что вы придрались к синтаксису.


mgu>Да нет, к подходу -- налицо излишняя многословность.


Разница только в количестве строк.

mgu> Против инкрементов у вас же возражений нет?


Инкременты откуда взялись?

S>>К коду AlexGin сходу можно предъявлять претензии гораздо более серьезные.


mgu>Например?


Да вот, первый же cpp-файл в репозитории. И сразу же:
bool SMSContentGreater(CSMSContent* pSMS1, CSMSContent* pSMS2) // Global function for std::sort
{
    CTime time1, time2;
    SYSTEMTIME st1, st2;
    if (pSMS1->GetSMSTime().GetAsSystemTime(st1))
        time1 = CTime(st1);
    if (pSMS2->GetSMSTime().GetAsSystemTime(st2))
        time2 = CTime(st2);

    time_t t1 = time1.GetTime();
    time_t t2 = time2.GetTime();

    if (t1 > t2)
        return true;
    else
        return false;
}

Здесь есть две последовательно выполняемые независимые операции -- извлечение времени в виде SYSTEMTIME и трансформация его в time_t через промежуточный CTime. Даже если предположить, что столь длинная цепочка нужна, то все равно непонятно, зачем нужны две пары переменных time1+time2 и st1+st2. Если можно обойтись всего одной переменной типа SYSTEMTIME и одной переменной типа CTime. Что-то вроде:
CTime ct;
SYSTEMTIME st;
if(pSMS1->GetSMSTime().GetAsSystemTime(st))
  ct = CTime(st);
time_t t1 = ct.GetTime();

if(pSMS2->GetSMSTime().GetAsSystemTime(st))
  ct = CTime(st);
time_t t2 = ct.GetTime();

Здесь становится очевидно, что имеется две однотипных операции и явная копи-паста. Которая устраняется через вспомогательную функцию:
namespace {
inline time_t GetTime(const CSMSContent & sms) {
  SYSTEMTIME st;
  return sms.GetSMSTime().GetAsSytemTime(st)) ? CTime(st).GetTime() : CTime().GetTime();
}
}

bool SMSContentGreater(CSMSContent * pSMS1, CSMSContent * pSMS2) {
  return GetTime(*pSMS1) > GetTime(*pSMS2);
}

И это все в рамках C++98/03, что несколько многословно. Можно воспользоваться возможностями не очень уже современного C++11 и имитацией локальных функций в нем:
bool SMSContentGreater(CSMSContent * pSMS1, CSMSContent * pSMS2) {
  auto GetTime = [](const CSMSContent & sms) {
    SYSTEMTIME st;
    return sms.GetSMSTime().GetAsSytemTime(st)) ? CTime(st).GetTime() : CTime().GetTime();
  };
  return GetTime(*pSMS1) > GetTime(*pSMS2);
}

Однако, особая пикантность ситуации состоит в том, что у CTime уже есть оператор "меньше". Посему непонятно, а зачем вообще нужна еще одна трансформация из CTime в time_t. Более того, очень похоже, что GetSMSTime уже возвращает объект типа CTime, у которого затем дергается GetAsSystemTime() дабы получить SYSTEMTIME. А затем из SYSTEMTIME вновь конструируется CTime... Чой-то неведомое.

И это только первая же функция в первом же файле. Смотрим этот же файл дальше:
CATCmdDevice::CATCmdDevice()
: m_pSerial(NULL), // Added 17.03.2015
  m_bIsGSMDeviceConnected(false) // Added 21.03.2015
{
    m_pTXBuff = NULL;  // Transmitter buffer
    m_pRXBuff = NULL;  // Reciver buffer

    m_bUnicodeMode = false;

    m_pPBRecord = NULL;

    m_bReceivedSMSListFull = false;
}

Конструктор. Только часть полей инициализируется через списки инициализации, часть -- в теле конструктора. Причем та часть, которая в теле конструктора, должна была бы инициализироваться в списках инициализации еще со времен C++98.

Дальше, деструктор:
CATCmdDevice::~CATCmdDevice()
{
    ClearSMSArr(); // Restored 01.10.2014

    if (m_pTXBuff)
    {
        delete[] m_pTXBuff;  
        m_pTXBuff = NULL;
    } 

    if (m_pRXBuff)
    {
        delete[] m_pRXBuff;  
        m_pRXBuff = NULL;
    }
}

Поля m_pTXBuff и m_pRXBuff объявлены в самом классе CATCmdDevice. Следовательно, занулять их в деструкторе после освобождения памяти смысла нет.

Опять же, на счет m_pTXBuff и m_pRXBuff: почему идет ручное управление памятью? Почему нельзя было воспользоваться std::vector (рекомендуемый путь со времен C++98)? Или вообще почему не сделать m_TXBuff и m_RXBuff обычными C-шными массивами?

Далее:
long CATCmdDevice::OpenSerial(int iComChannel, int iComBaudRate)
{
    if (m_pSerial)
        delete m_pSerial;

    m_pSerial = new CSerial();
    if (m_pSerial != NULL)
    {   // m_pSerial->Open(1, 9600);
        BOOL bOpen = m_pSerial->Open(iComChannel, iComBaudRate); 
        if(!bOpen)
        {
            g_log.SaveLogFile(PBK_ERROR, "Error during opening port: COM%u (baud rate = %u)",iComChannel,iComBaudRate);
            return 1L; // Error occur
        }
        else
            g_log.SaveLogFile(PBK_DEBUG, "Port: COM%u (baud rate = %u) - opening success!",iComChannel,iComBaudRate);
    }
    return 0L; // OK!
}

Что за проверка m_pSerial != NULL после new? Неужели автор транслирует свой код с запретом C++ных исключений на уровне ключей компилятора? Если даже он делает именно так, то где ветка else у этого if-а? А то ведь получается, что при запрещенных исключениях у него нет обработки ошибки выделения памяти (даже если в m_pSerial окажется 0, функция OpenSerial все равно вернет 0 в качестве признака успешного завершения). Если же исключения не запрещены, то данная проверка не имеет смысла, т.к. при недостатке памяти new бросит bad_alloc.

И это, повторюсь, всего лишь беглый просмотр всего лишь первого файла.

Несомненное достоинство данного кода -- это возможность в нем разобраться. Но общее впечатление, что его писал вчерашний студент, который только-только начал изучать язык C++.

По остальным вопросам в следующем ответе.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.