NB: Esta não é uma questão sobre como usar funções inline ou como elas funcionam, mas por que são feitas da maneira que são.
A declaração de uma função de membro de classe não precisa definir uma função inline
, pois é apenas a implementação real da função. Por exemplo, no arquivo de cabeçalho:
struct foo{
void bar(); // no need to define this as inline
}
Então, por que a implementação em linha de um aulas funcionam têm de estar no arquivo de cabeçalho? Por que não consigo colocar a função embutida no .cpp
arquivo? Se eu tentasse colocar a definição embutida no .cpp
arquivo, receberia um erro nas linhas de:
error LNK2019: unresolved external symbol
"public: void __thiscall foo::bar(void)"
(?bar@foo@@QAEXXZ) referenced in function _main
1>C:\Users\Me\Documents\Visual Studio 2012\Projects\inline\Debug\inline.exe
: fatal error LNK1120: 1 unresolved externals
inline
aparece uma definição, mas não uma declaração anterior vs vice-versa . Em caso afirmativo, isso pode ajudar: stackoverflow.com/questions/4924912/…Respostas:
A definição de uma
inline
função não precisa estar em um arquivo de cabeçalho, mas, por causa da regra de definição única ( ODR ) para funções inline, uma definição idêntica para a função deve existir em cada unidade de tradução que a usa.A maneira mais fácil de fazer isso é colocar a definição em um arquivo de cabeçalho.
Se você deseja colocar a definição de uma função em um único arquivo de origem, não deve declará-la
inline
. Uma função não declaradainline
não significa que o compilador não possa embutir a função.Se você deve declarar uma função
inline
ou não, geralmente é uma escolha que você deve fazer com base em qual versão das regras de definição faz mais sentido seguir; adicionarinline
e ser restringido pelas restrições subsequentes faz pouco sentido.fonte
+1
minha!Existem duas maneiras de ver isso:
As funções embutidas são definidas no cabeçalho porque, para embutir uma chamada de função, o compilador deve ser capaz de ver o corpo da função. Para um compilador ingênuo fazer isso, o corpo da função deve estar na mesma unidade de tradução da chamada. (Um compilador moderno pode otimizar as unidades de tradução e, portanto, uma chamada de função pode ser embutida, mesmo que a definição da função esteja em uma unidade de tradução separada, mas essas otimizações são caras, nem sempre estão habilitadas e nem sempre são suportadas pelo compilador)
as funções definidas no cabeçalho devem ser marcadas
inline
porque, caso contrário, cada unidade de tradução que inclui o cabeçalho conterá uma definição da função, e o vinculador reclamará sobre várias definições (uma violação da Regra de Uma Definição). Ainline
palavra-chave suprime isso, permitindo que várias unidades de tradução contenham definições (idênticas).As duas explicações realmente se resumem ao fato de que a
inline
palavra - chave não faz exatamente o que você esperava.Um compilador C ++ é livre para aplicar a otimização inlining (substituir uma chamada de função pelo corpo da função chamada, economizando a sobrecarga da chamada) a qualquer momento, desde que não altere o comportamento observável do programa.
A
inline
palavra-chave torna mais fácil para o compilador aplicar essa otimização, permitindo que a definição da função seja visível em várias unidades de tradução, mas usar a palavra-chave não significa que o compilador tenha que embutir a função, e não usar a palavra-chave não proíba o compilador de embutir a função.fonte
Este é um limite do compilador C ++. Se você colocar a função no cabeçalho, todos os arquivos cpp onde ela pode ser embutida podem ver a "fonte" de sua função e a sequência pode ser feita pelo compilador. Caso contrário, o inlining teria que ser feito pelo vinculador (cada arquivo cpp é compilado em um arquivo obj separadamente). O problema é que seria muito mais difícil fazer isso no vinculador. Um problema semelhante existe com classes / funções de "modelo". Eles precisam ser instanciados pelo compilador, porque o vinculador teria problemas para instanciar (criar uma versão especializada) deles. Algum compilador / vinculador mais recente pode fazer uma compilação / vinculação de "duas passagens", onde o compilador faz uma primeira passagem, então o vinculador faz seu trabalho e chama o compilador para resolver coisas não resolvidas (embutidos / modelos ...)
fonte
O motivo é que o compilador precisa realmente ver a definição para poder inseri-la no lugar da chamada.
Lembre-se de que C e C ++ usam um modelo de compilação muito simplista, onde o compilador sempre vê apenas uma unidade de tradução por vez. (Falha na exportação, que é o principal motivo pelo qual apenas um fornecedor o implementou.)
fonte
A
inline
palavra-chave c ++ é enganosa, não significa "embutir esta função". Se uma função for definida como embutida, significa simplesmente que pode ser definida várias vezes, desde que todas as definições sejam iguais. É perfeitamente válido para uma função marcadainline
para ser uma função real que é chamada em vez de obter o código embutido no ponto onde é chamada.Definir uma função em um arquivo de cabeçalho é necessário para modelos, uma vez que, por exemplo, uma classe com modelo não é realmente uma classe, é um modelo para uma classe da qual você pode fazer várias variações. Para que o compilador seja capaz de, por exemplo, fazer uma
Foo<int>::bar()
função quando você usa o modelo Foo para criar uma classe Foo , a definição real deFoo<T>::bar()
deve estar visível.fonte
inline
(nem a não declaraçãoinline
garante que ela não será sequencial).Eu sei que este é um tópico antigo, mas pensei que deveria mencionar a
extern
palavra - chave. Recentemente, encontrei esse problema e resolvi da seguinte maneiraHelper.h
Helper.cpp
fonte
Porque o compilador precisa vê-los para colocá-los em linha . E os arquivos de cabeçalho são os "componentes" normalmente incluídos em outras unidades de tradução.
fonte
Funções Inline
Em C ++, uma macro nada mais é do que uma função embutida. SO agora as macros estão sob controle do compilador.
O código da função Inline é substituído no local em que é chamado, reduzindo assim a sobrecarga da função de chamada.
Em alguns casos, a função embutida pode não funcionar, como
Se a variável estática for usada dentro da função embutida.
Se a função é complicada.
Se chamada recursiva de função
Se o endereço da função for tomado implícita ou explicitamente
Função definida fora da classe conforme abaixo pode se tornar embutida
A função definida dentro da classe também se torna embutida
Aqui, as funções getSpeed e setSpeed ficarão embutidas
fonte