Pergunta

A maioria dos programadores C ++ como eu ter feito o seguinte erro em algum momento:

class C { /*...*/ };

int main() {
  C c();     // declares a function c taking no arguments returning a C,
             // not, as intended by most, an object c of type C initialized
             // using the default constructor.
  c.foo();   // compiler complains here.

  //...
}

Agora, enquanto o erro é bastante óbvio uma vez que você sabe que eu queria saber se há alguma utilização sensata para esse tipo de declaração da função local, exceto que você pode fazê-lo - especialmente porque não há nenhuma maneira de definir uma função tal local no mesmo bloco; você tem que defini-lo em outro lugar.

Eu acho que Java-style classes locais são uma característica muito legal que eu tendem a usar muitas vezes, especialmente o tipo anônimo. Mesmo as classes locais C ++ (que podem ter funções membro inline-definidos) tem alguma utilidade. Mas esta declaração da função local sem coisa definição parece muito estranho para mim. É apenas um C-legado ou se há algum caso de uso mais profunda que eu não estou ciente de?

Editar para os não-crentes:. C c() é não uma declaração ponteiro de função

Este programa

int main()
{
  void g();
  cout << "Hello ";
  g();
  return 0;
}

void g()
{
  cout << "world." << endl;
}

saídas Hello world. Este programa

void fun()
{
  cout << "world." << endl;
}

int main()
{
  void g();
  g = fun;
  cout << "Hello ";
  g();
  return 0;
}

não compila. gcc reclama:

error: cannot convert 'void ()()' to 'void ()()' in assignment

comeau:

error: expression must be a modifiable lvalue
Foi útil?

Solução

Eu queria declarações de função locais em C quando eu queria passá-las como argumentos para alguma outra função. Eu faço isso o tempo todo em outros idiomas. A razão é encapsular a implementação de estruturas de dados.

por exemplo. Defino alguma estrutura de dados, por exemplo uma árvore ou um gráfico, e eu não quero expor os detalhes de sua implementação interna, por exemplo, porque eu pode querer alterar ou variar-lo. Então eu expor acessor e funções modificadores para seus elementos, e uma função de passagem para iterar sobre os elementos. A função de passagem tem como argumento uma função que opera em um elemento; a tarefa do função de passagem é para executar a função argumento em cada elemento e, possivelmente, agregar os resultados de alguma forma. Agora, quando eu chamar a função de passagem, a função argumento é geralmente alguma operação especializado que depende do estado local e, portanto, deve ser definida como uma função local. Ter que empurrar a função, com as variáveis ??que contêm o estado local, do lado de fora para ser global, ou em uma classe interna criada especificamente para mantê-los, é bunda feia. Mas este é um problema que tenho com C e Java, não com C ++.

Outras dicas

O único uso que eu posso pensar é reduzir o escopo de declarações de função:

int main()
{
    void doSomething();
    doSomething();
    return 0;
}

void otherFunc()
{
    doSomething();  // ERROR, doSomething() not in scope
}

void doSomething()
{
    ...
}

É claro, há muito melhores soluções para este. Se você precisa esconder uma função, você deve realmente reestruturar seu código movendo funções em módulos separados para que as funções que precisam chamar a função que você deseja ocultar estão todos no mesmo módulo. Então, você pode fazer esse módulo-local função, declarando-estático (o caminho C) ou, colocando-o dentro de um namespace anônimo (a forma como C ++).

É um protótipo declaração para a frente. É concebível que se você tem um monte de funções locais, ou funções locais que chamam um ao outro contra a ordem de definição, você pode precisar dele.

O uso somente sane por isso que eu posso ver é permitir que apenas uma função em uma unidade de compilação de saber sobre uma função definida em outra unidade de compilação. Eu acho que seria um uso um pouco razoável, mas que é o único que eu posso pensar, e eu acho que isso é um exagero.

Como disse no 3º trecho de esta resposta , pode ajudar com sombreamento escopo.

#include <stdio.h>

void c(); // Prototype of a function named ``c''

int main() {

    c(); // call the function

    { // additional scoppe needed for C, not for C++
        int c = 0; // shadow the c function with a c integer variable
        c++;
        {
            void c(); // hide the c integer variable back with the c function
            c();
        }
        ++c;
    } //!

    return 0;
}

void c() {
    printf("Called\n");
}

Eu não acho que essa utilização é susceptível de ser útil muitas vezes e há chances de que ele não vai surgir em qualquer programa bem desenhado.

Eu ainda acho que essa é a razão mais provável para esse recurso, definindo funções ultimamente como para as variáveis ??apenas não soa tão certo.

Às vezes eu fazê-lo pela mesma razão, somos encorajados a variáveis ??de declaração de direito antes da primeira utilização (e não antes), ou seja, para melhorar a legibilidade. (Sim, eu percebo que para as variáveis ??é mais importante porque alivia a necessidade de verificar se a variável é usado antes que você acha que é a sua primeira utilização). Tendo o protótipo (especialmente se ele está mais envolvido do que apenas c()) perto da invocação da função melhora a legibilidade. O fato de que o C c() caso especial é enganosa para os seres humanos é lamentável, mas a idéia geral de funções declarando tem localmente mérito.

Claro, isso é verdade também para nomes de função que já estão no escopo. Por que não redeclare todas as funções antes de cada seu uso? Minha resposta para isso: fazer todas as coisas com moderação. Demasiada impede desordem legibilidade (bem como manutenção --- deve ser o da função de assinatura já mudança). Então, enquanto eu não iria fazer uma regra de fora, às vezes é útil para declarar funções localmente.

Se você quiser diferem entre declarar uma função de tomar sem parâmetros e instanciar uma classe com destructor padrão, pule o parêntese.

class C
{
  public:
    void foo() {}
};


int main()
{
    // declare function d, taking no arguments, returning fresh C
    C d();

    // instantiate class (leave parenthesis out)
    C c;
    c.foo();

    // call declared function
    C goo = d();

    return 0;
}

C d()
{
    C c;
    // ..
    return c;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top