Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Шесть загадок по С

Anna | 24.06.2014 | нет комментариев

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

Дабы было увлекательнее, материал представлю в виде примитивных задачек. Сразу подчеркну, что я не считаю приведенные примеры просчетами языка. Во многом возникает толк и логика, если вопрос обдумать. Это скорее случаи, когда может отказать интуиция, исключительно если голова забита чем-нибудь еще. Есть и пара примеров вида «Ну чего этому компилятору нужно, только что то же самое работало!»

И последнее примечание. Это не будут задачи на наблюдательность типа «Здесь я поставил точку с запятой сразу позже for — а никто и не подметил». Задачи не в опечатках. Все нужные библиотеки дозволено считать подключенными — не относящийся к описываемой обстановки код я спускал, Дабы не загромождать статью.

Условие всех задач.

Дан определенный код. Изредка он разбит на отдельные листинги. Необходимо ответить, скомпилируется ли программа, а если скомпилируется, что будет выведено на экран, и как себя поведет приложение, если компиляция завершится с оплошностью, то по какой причине.

Задача 1. Разделяем на 0

 

Листинг 1.1:

 

    int g = 3;
    g -= 3;
    int f = 1 / g;
    std::cout << "f is " << f << std::endl;

 

Листинг 1.2:

 

    float g = 3;
    g -= 3;
    float f = 1 / g;
    std::cout << "f is " << f << std::endl;

 

Результат

Листинг 1.1 Программа аварийно завершает работу. На нуль разделять невозможно. Именно то, чего ждешь.
Листинг 1.2 Все работает. Итог «f is inf». По каждой видимости, считается, что float не является точным типом, потому и нуля как такового в нем представлено быть не может. Только беспредельно малое. А на беспредельно малое разделять дозволено. Об этом необходимо помнить и не верить, что в случае деления на нуль программа упадет, и вы сразу узнаете об ошибке.
Задача 2. Switch и класс

 

Листинг 2

 

class SwitchClass
{
public:
    static const int ONE;
    static const int TWO;

    void switchFun(int number)
    {
        switch(number)
        {
        case ONE:
          std::cout<<"1"<<std::endl;
           break;
        case TWO:
          std::cout<<"2"<<std::endl;
           break;
        }
    }
};
const int SwitchClass::ONE = 1;
const int SwitchClass::TWO = 2;

int main()
{
   SwitchClass object;
   object.switchFun(SwitchClass::ONE);
   return 0;
}

 

Результат

Не компилируется. Статические константные члены класса не являются с точки зрения оператора switch довольно константными. Задача решается применением перечислений (enum) взамен “static const int
Задача 3. Логические выражения

 

Листинг 3

 

bool update1()
{
    std::cout<<"update1"<<std::endl;
    ...//Выполнение обновления и возврат итога
}

bool update2()
{
    std::cout<<"update2"<<std::endl;
    ... //Выполнение обновления и возврат итога
}

int main()
{
    bool updatedSuccessfully = update1() && update2();
    return 0;
}

 

Результат

Итог на экран будет зависеть от того, какое значение вернет update1. В C вычисление логических выражений оптимизируется. Т.е., если на каком-то этапе итог становится явствен — последующие расчеты не выполняются. В примере применяется логическое И. Если один из его операндов ВРАНЬЕ, то итог тendl; } void fun(std::string s) { std::cout<<”string”<<std::endl; } }; class TestVirtualsChild : public TestVirtuals { public: virtual void fun(int i) { std::cout<<”int child”<<std::endl; } };

Листинг 6.2
    TestVirtuals tv;
    tv.fun(1);
    tv.fun(1.f);
    tv.fun(std::string("one"));
Листинг 6.3
    TestVirtualsChild tvc;
    tvc.fun(1);
    tvc.fun(1.f);
Листинг 6.4
    TestVirtualsChild tvc;
    tvc.fun(std::string("one"));

Результат

Листинг 6.2 Перегрузка отработает, как и ожидалось. Итог программы

int
float
string

Листинг 6.3 Потомок «не видит» перегрузки родителя. Все вызовы способа fun приводятся к целочисленному варианту (тот, что есть в потомке). Итог программы

int child
int child

Листинг 6.4 Компиляция завершается с оплошностью. Невиртуальная функция как словно пропадает у потомка. Остается допустимым только очевидный ее вызов через очевидное указание родительского класса.

    tvc.TestVirtuals::fun(std::string("one"));

Итог. От совмещения виртуальных функций с перегруженными отменнее держаться подальше. Если иного выхода нет, осторожность должна легко зашкаливать.

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB