Среда, 15.08.2018, 06:36
Discovery
Главная Регистрация Вход
Приветствую Вас, Гость · RSS
Меню сайта
Форма входа
Категории раздела
PHP [1]
Уроки по PHP для начинающих
C++ [18]
Статьи посвященные С++
XML [2]
Статьи по XML
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
     Каталог статей
    -->
    Главная » Статьи » Программирование » C++

    Функции: правила видимости переменных.

    Функции: правила видимости переменных.

    При использовании функций часто возникает проблема, как вернуть из функции больше одного значения. Дело в том, что из функции с помощью функции return можно вернуть только значение одной переменной. А если нам нужно вернуть из функции больше одного значения? Например, результат деления двух чисел или невозможность выполнить деление, если делитель равен нулю. Другой пример: извлечение корня из отрицательного числа. Если бы в С++ не было предусмотрено решения данной проблемы, он вряд ли стал бы любимым языком профессиональных программистов. Но сначала я хочу рассказать о правилах видимости переменных в функциях, и передаче аргументов по значению и по ссылке. И так начнем правил видимости переменных.

    Как мы знаем все переменные делятся на локальные и глобальные. Глобальные переменные видны в любом месте программы. Локальные переменные видны в пределах нескольких инструкций отделенных фигурными скобками. Инструкции, находящиеся между фигурными скобками еще называют блоком.

    Если в функции main() объявить переменную int test и точно такую же переменную, с тем же именем внутри функции void local(), которую мы вызываем из функции main(), то обе переменные никак не будут между собой связаны. Это значит, что если мы в функции local() изменим, значение переменной test, то в функции оно останется прежним. Каждый раз, когда мы вызываем функцию local() выделяется место для переменной int test, а после того как функция завершила свою работу переменная разрушается. При повторном вызове функции local() она создается заново. В этом вы можете убедиться сами, выполнив следующую программу:

    #include <iostream>
    #include <windows.h>
    using namespace std;

    void local();

    int main()
    {
        int test = 10;

        cout << "Значение переменной test в функции main()\n"
               << "до вызова функции local: " << test << "\n\n";

        local();

        cout << "Значение переменной test в функции main()\n"
               << "после вызова функции local: " << test;

        cout << "\n\n";
        system("PAUSE");
        return 0;
    }

    void local()
    {
        int test = 20;

        cout << "Значение переменной test в функции"
               << " local: " << test << "\n\n";
    }

    Результат будет следующим:

    Значение переменной test в функции main()
    до вызова функции local: 10

    Значение переменной test в функции local: 20

    Значение переменной test в функции main()
    после вызова функции local: 10

    Для продолжения нажмите любую клавишу . . .

    Как видим изменение переменной test в функции local() никак не отразилось на переменной test объявленной в функции main(). Дело в том, для компилятора это не одна переменная, а две у которых совпадают имя и тип.

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

    #include <iostream>
    #include <windows.h>
    using namespace std;

    void local(int test);

    int main()
    {
        int test = 10;

        cout << "Значение переменной test в функции main()\n"
               << "до вызова функции local: " << test << "\n\n";

        local(test);

        cout << "Значение переменной test в функции main()\n"
               << "после вызова функции local: " << test;

        cout << "\n\n";
        system("PAUSE");
        return 0;
    }

    void local(int test)
    {
        test = 20;

        cout << "Значение переменной test в функции"
               << " local: " << test << "\n\n";
    }

    Результат выполнения этой программы будет таким же, как и предыдущей. В чем тут дело? Для начала важно запомнить то, что находиться внутри скобок в прототипе функции и в ее реализации называется параметрами, а то, что находиться внутри скобок при ее вызове называется аргументами функции. Когда мы передаем в качестве аргумента имя переменной, ее значение копируется в параметр функции. То, что происходит внутри функции, никак не отражается на значении переменной, используемой при вызове функции. Это называется передачей аргументов по значению (передается только значение, а не сама переменная). Но можно в качестве аргумента передать функции указатель на переменную. Переделаем нашу программу, передав в качестве аргумента указатель на переменную test:

    #include <iostream>
    #include <windows.h>
    using namespace std;

    void local(int* test);

    int main()
    {
        int test = 10;

        cout << "Значение переменной test в функции main()\n"
               << "до вызова функции local: " << test << "\n\n";

        local(&test);

        cout << "Значение переменной test в функции main()\n"
               << "после вызова функции local: " << test;

        cout << "\n\n";
        system("PAUSE");
        return 0;
    }

    void local(int* test)
    {
        *test = 20;

        cout << "Значение переменной test в функции"
               << " local: " << *test << "\n\n";
    }

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

    Можно автоматизировать этот процесс с помощью ссылочных параметров. И так вот как будет выглядеть та же самая программа с использованием ссылочных параметров:

    #include <iostream>
    #include <windows.h>
    using namespace std;

    void local(int &test);

    int main()
    {
        int test = 10;

        cout << "Значение переменной test в функции main()\n"
               << "до вызова функции local: " << test << "\n\n";

        local(test);

        cout << "Значение переменной test в функции main()\n"
               << "после вызова функции local: " << test;

        cout << "\n\n";
        system("PAUSE");
        return 0;
    }

    void local(int &test)
    {
        test = 20;

        cout << "Значение переменной test в функции"
               << " local: " << test << "\n\n";
    }

    Ссылочный параметр объявляется с помощью знака, & который должен предшествовать параметру в объявлении функции. При этом при вызове функции знак & перед именем переменной ставить не надо. Иначе компилятор выдаст ошибку. Теперь если изменять значение переменной в функции, то оригинал, то же измениться.

    Еще один важный момент. Как я уже говорил переменная объявленная внутри функции, создается при вызове функции, а после завершения разрушается. А что делать, если мы хотим сохранить значения переменной между вызовами? Для этого можно использовать ключевое слово static.

    #include <iostream>
    #include <windows.h>
    using namespace std;

    void local();

    int main()
    {
            cout << "Первый вызов функции local().\n\n";

        local();

        cout << "Второй вызов функции local().\n\n";

        local();

        cout << "Третий вызов функции local().\n\n";

        local();

        cout << "\n\n";
        system("PAUSE");
        return 0;
    }

    void local()
    {
        static int test = 0;

        for(int i=0; i<=4; i++)
        {
            test++;
            cout << test << "\n";
        }
        cout << "\n\n";
    }

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

    #include <iostream>
    using namespace std;

    double division(double num1, double num2, bool* success);

    int main()
    {
        bool exit = 1;
        bool success;
        double num1, num2, total;
        char choice[1];

        while(exit)
        {
            cout << "Введите первое число: \n\n";
            cin >> num1;
            cout << "\n";
            cout << "Введите второе число: \n\n";
            cin >> num2;
            cout << "\n";

            total = division(num1, num2, &success);

            if(success)
            {
                cout << "Результат: " << total << "\n\n";

                cout << "Хотите попробовать еще раз? (Y/N)";

                cin >> choice;

                cout << "\n";

                if(!strcmp(choice, "y") || !strcmp(choice, "Y"))
                    exit = 1;
                else if(!strcmp(choice, "n") || !strcmp(choice, "N"))
                    return 0;
            }
            else
            {
                cout << "На ноль делить нельзя!\n\n"
                       << "Хотите попробовать ввести заново? (Y/N)";

                cin >> choice;

                cout << "\n";

                if(!strcmp(choice, "y") || !strcmp(choice, "Y"))
                    exit = 1;
                else if(!strcmp(choice, "n") || !strcmp(choice, "N"))
                    return 0;
            }
        }
        return 0;
    }

    double division(double num1, double num2, bool* success)
    {
        double total;

        if(num2 == 0)
            *success = 0;
        else
        {
            total = num1/num2;
            *success = 1;
        }
        return total;
    }

    Обратите внимание на то, что инструкция return 0; в нашей программе написана несколько раз. Дело в том, что функция main() то же возвращает значение типа int. Строчка return 0; означает, что функция успешно выполнена и программа может завершить свою работу. Поэтому, как только программа встречает в функции main() эту инструкцию она завершает свою работу. Теперь напишем ту же самую программу с использованием ссылочных параметров:

    #include <iostream>
    using namespace std;

    double division(double num1, double num2, bool &success);

    int main()
    {
        bool exit = 1;
        bool success;
        double num1, num2, total;
        char choice[1];

        while(exit)
        {
            cout << "Введите первое число: \n\n";
            cin >> num1;
            cout << "\n";
            cout << "Введите второе число: \n\n";
            cin >> num2;
            cout << "\n";

            total = division(num1, num2, success);

            if(success)
            {
                cout << "Результат: " << total << "\n\n";

                cout << "Хотите попробовать еще раз? (Y/N)";

                cin >> choice;

                cout << "\n";

                if(!strcmp(choice, "y") || !strcmp(choice, "Y"))
                    exit = 1;
                else if(!strcmp(choice, "n") || !strcmp(choice, "N"))
                    return 0;
                }
            else
            {
                cout << "На ноль делить нельзя!\n\n"
                       << "Хотите попробовать ввести заново? (Y/N)";

                cin >> choice;

                cout << "\n";

                if(!strcmp(choice, "y") || !strcmp(choice, "Y"))
                    exit = 1;
                else if(!strcmp(choice, "n") || !strcmp(choice, "N"))
                    return 0;
                }
            }
        return 0;
    }

    double division(double num1, double num2, bool &success)
    {
        double total;

        if(num2 == 0)
            success = 0;
        else
        {
            total = num1/num2;
            success = 1;
        }
        return total;
    }

    На следующем уроке мы продолжим изучение функций.

    Категория: C++ | Добавил: stranger140569 (12.06.2013)
    Просмотров: 1318 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Имя *:
    Email *:
    Код *:
    Copyright MyCorp © 2018
    Конструктор сайтов - uCoz