Передать текущее состояние функции в другую функцию в C / C ++ - PullRequest
3 голосов
/ 04 февраля 2010

Есть ли способ передать текущее состояние функции в другую функцию в C / C ++?Я имею в виду все параметры и локальные переменные под текущим состоянием.Например:

void funcA (int a, int b)
{
    char c;
    int d, e;
    // Do something with the variables.
    // ...
    funcB();
    // Do something more.
}

void funcB()
{
    // funcB() should be able to access variables a,b,c,d & e
    // and any change in these variables reflect into funcA().
}

Код имеет плохую форму, если есть необходимость в функциях типа funcB().Но можно ли этого достичь?

Это может помочь, если кто-то начинает перефакторизовать длинный метод с несколькими параметрами.

Ответы [ 9 ]

7 голосов
/ 04 февраля 2010

Введите общую структуру.

struct State {
    char c;
    int d,e;
};

void funcA(int a, int b){
    State s;
    s.d = 1234; // ...
    // ...
    funcB(s);
}

void funcB(State& s)
{
    //...
}
5 голосов
/ 04 февраля 2010

gcc поддерживает Pascal-подобное расширение C, а именно вложенные функции, например,

#include <stdio.h>

int main(void)
{
    int a = 1, b = 2;

    void foo(void)
    {
        printf("%s: a = %d, b = %d\n", __FUNCTION__, a, b);
    }

    printf("%s: a = %d, b = %d\n", __FUNCTION__, a, b);

    foo();

    return 0;
}

Скомпилируйте это с помощью --nested-functions:

$ gcc -Wall --nested-functions nested.c -o nested

и затем запустите

$./nested
main: a = 1, b = 2
foo: a = 1, b = 2

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

3 голосов
/ 04 февраля 2010

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

struct SomeAlgo {
    SomeAlgo()
    : c(0), d(0), e(0) // Initialize common variables
    { }
    void funcA(int a,int b)
    {
        c = 1234; //...
        // ...
        funcB();

    }
    void funcB() // You may put it in the private section.
    {
        // Simply use c,d,e here.
    }
private:
    char c;
    int d,e;
};

Использование

SomeAlgo alg;
alg.funcA(3,4);

РЕДАКТИРОВАНИЕ: Участники не статичны. Лучше так.

2 голосов
/ 04 февраля 2010

Создайте структуру для хранения всех состояний, которые вас интересуют.

Запишите обе функции в терминах структуры;то есть они принимают в качестве своего единственного параметра экземпляр структуры, и все состояния сохраняются в структуре.

struct foo {  int d; int e; char c ; } fooinstance;

void afunc( struct foo fi);
void bfunc( struct foo fi);

void afunc( struct foo fi ) {
  // do stuff with fi
  f1.d += fi.e ;
  fi.c++;
  // call b
  b(fi);
}

Затем передают экземпляр структуры от a к b.Более эффективным было бы передать указатель на структуру, но передача структуры будет работать.

1 голос
/ 04 февраля 2010

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

1 голос
/ 04 февраля 2010

Это может помочь, если кто-то начинает перефакторизовать длинный метод с несколькими параметрами.

Чтобы решить эту конкретную проблему, вы можете использовать объекты и просто связать в конструкторе некоторые изчасто используемые параметры для членов объекта.А затем сделайте ваши функции (которые принимают эти длинные списки параметров) членами-функциями.

1 голос
/ 04 февраля 2010

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

0 голосов
/ 04 февраля 2010

Что вы, вероятно, хотите сделать, это: инкапсулировать ваши функции в класс и создать его единственный экземпляр.Состояние, которое вы хотите разделить между этими функциями, - это то, что технически происходит в ООП путем создания экземпляров объектов и вызова для них методов.

Так что, если C ++ является опцией (так как C не имеет ООП), я бы рекомендовал использовать это решение.

Другим подходом было бы использование лямбда-выражений / замыканий, но это не вариант в C / C ++, поскольку он не поддерживает эти языковые конструкции.

Редактировать: Толькоиспользуйте синглтоны, если вы знаете, как правильно обрабатывать их в коде ...

0 голосов
/ 04 февраля 2010

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

. Как и предполагали другие, я бы либо создал структуру только для этой цели, либо передал бы все необходимые переменные по ссылке, чтобы прояснить это.на что funcB опирается.

...