funções aninhadas não são permitidos, mas por protótipos de funções aninhadas são permitidos? [C ++]

StackOverflow https://stackoverflow.com/questions/928992

Pergunta

a questão ligada que me leva a fazer esta pergunta.

Considere o seguinte código

int main()
{
    string SomeString();
}

Todos diz, compilador toma isso como um protótipo de função e não como um string objeto. Agora, considere o seguinte código.

int main()
{
    string Some()
    {
        return "";
    }
}

Compiler disse que esta é inválido como eu acho que definição de função aninhada não é permitido. Se não é permitido, por protótipos de funções aninhadas são permitidos? Não está a dar qualquer vantagem ao invés de fazer confusão (ou estou faltando alguns pontos válidos aqui?).

Eu descobri o seguinte é válido.

int main()
{ 
  string SomeFun();
  SomeFun();
  return 0;
}

string SomeFun()
{
  std::cout << "WOW this is unexpected" << std::endl;
}

Isso também é confuso. Eu estava esperando a função somefun () terá um escopo somente no main . Mas eu estava errado. Por compilador está permitindo para compilar o código como o acima? Existe alguma tempo real situações em que o código como o sentido marcas acima?

Qualquer pensamento?

Foi útil?

Solução

Seu protótipo é apenas ' Atacante Declaração '. Por favor, confira o artigo da Wikipedia.

Basicamente, ele diz ao compilador "não se assuste se o rótulo 'somefun' é usado dessa maneira". Mas o vinculador é o que é responsável por encontrar o corpo da função correta.

Você pode realmente declarar um protótipo falso, por exemplo, 'Somefun char ()' e usá-lo em todo o seu principal. Você só receberá um erro quando o vinculador tenta encontrar o corpo de sua função de falso. Mas seu compilador vai ser legal com ele.

Existem muitos benefícios. Você tem que lembrar o corpo da função não é sempre no mesmo arquivo de código fonte. Pode ser em um library.Also ligada, essa biblioteca vinculado pode ser ter um específico 'elo signature'.Use define condicionais você pode até selecionar a assinatura link correto em tempo de compilação usando seus escopo prototypes.Although a maioria das pessoas iria usar ponteiros de função para que em vez.

Espero que isso ajude.

Outras dicas

Assim como uma nota lateral, C ++ 03 tem uma forma indireta de definição de funções locais. Exige abusar o recurso de classe local:

int main()
{
    struct Local
    {
        static string Some()
        {
            return "";
        }
    };
    std::cout << Local::Some() << std::endl;
}

Esta é uma convenção de C - como muitos -. Que C ++ tem adotado

A capacidade de declarar uma função dentro de outra função em C é uma decisão que a maioria dos programadores provavelmente considerar lamentável e desnecessário. Particularmente com design OOP moderna, onde as definições de função são comparativamente menores do que eles estão em C.

Se você gostaria de ter funções que só existem no âmbito de uma outra função, há duas opções boost :: lambda e C ++ 1x lambda .

Quanto ao porquê de sua declaração de

void f() {
    void g(); g();
}

é melhor do que este

void g();
void f() {
    g();
}

Em geral, é bom se você manter declarações como local quanto possível, de modo que o menor número de conflitos de nomes como resultado possível. Eu digo que é discutível se declarar uma função localmente (desta forma) é realmente sorte, como eu acho que é ainda melhor ordinária incluir seu cabeçalho e depois ir para o caminho "normal", o que também é menos confuso para é as pessoas não saber sobre isso. Às vezes, também é útil para contornar uma função sombreada

void f() {
    int g; 
    // oops, ::g is shadowed. But we can work around that
    {
        void g(); g();
    }
}

Claro que, em C ++ que poderíamos chamar g função usando its_namespace::g() - mas nos velhos tempos de C, que não teria sido possível, e essa coisa permitido o programador ainda acessar a função. Observe também que, embora sintaticamente não é o mesmo, semanticamente a seguir faz também declarar uma função dentro de um escopo local, que realmente tem como alvo um escopo diferente.

int main() {
    using std::exit;
    exit();
}

Como uma nota lateral, há mais situações como aquela onde o escopo alvo de uma declaração é não o escopo em que essa declaração aparece. Em geral, a entidade declarar se torna um membro da âmbito em que a declaração aparece. Mas isso nem sempre é o caso. Considere, por exemplo declarações amigo, onde essa coisa acontece

struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!

Mesmo que a declaração da função (e definição!) De f aconteceu no âmbito da X, a entidade (a própria função) tornou-se um membro do espaço de nomes de inclusão.

Função protótipos são dicas para o compilador. Eles indicam que as funções são implementadas em outro lugar, se já não estiver descoberto . Nada mais.

Quando você declarar um protótipo que você está fazendo, você está basicamente dizendo o compilador para esperar o vinculador para resolvê-lo. Dependendo de onde você escreve o protótipo as regras de escopo se aplicam. Não há nada tecnicamente errado escrever o protótipo dentro de sua função main () (embora IMHO um pouco mais confusa), isso significa apenas que a função só é conhecida localmente dentro do main (). Se você teria declarado o protótipo na parte superior do seu arquivo de origem (ou, mais comumente, em um arquivo de cabeçalho), o / função protótipo seria conhecido em toda a fonte.

string foo()
{
  string ret = someString();  // Error
  return ret; 
}

int main(int argc,char**argv)
{
   string someString();
   string s = somestring(); // OK
   ...
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top