2009-06-05 9 views
22

Sto tentando di utilizzare le funzioni membro inline di una particolare classe. Ad esempio la dichiarazione di funzione e l'attuazione senza inlining in quanto tale:Errore linker funzione inline

nel file di intestazione:

int GetTplLSize(); 

nel file cpp:

int NeedleUSsim::GetTplLSize() 
{ 
    return sampleDim[1]; 
} 

Per qualche ragione, se ho messo il " "inline" parola chiave in uno dell'implementazione e dichiarazione, così come in entrambi i luoghi, ricevo errori linker come mostrato:

 
Creating library C:\DOCUME~1\STANLEY\LOCALS~1\TEMP\MEX_HN~1\templib.x and object C:\DOCUME~1\STANLEY\LOCALS~1\TEMP\MEX_HN~1\templib.exp 
mexfunction.obj : error LNK2019: unresolved external symbol "public: int __thiscall NeedleUSsim::GetTplLSize(void)" ([email protected]@@QAEHXZ) referenced in function _mexFunction 
mexfunction.mexw32 : fatal error LNK1120: 1 unresolved externals 

    C:\PROGRA~1\MATLAB\R2008B\BIN\MEX.PL: Error: Link of 'mexfunction.mexw32' failed. 

Cosa deve essere necessario per eliminare questo errore (ad es. cosa sto facendo male in termini di rendere queste funzioni membro inline)?

risposta

23

È necessario inserire la definizione di funzione nell'intestazione. Il modo più semplice per suggerire al compilatore di linea è quello di includere il metodo corpo nella dichiarazione di classe come:


class NeedleUSsim 
{ 
    // ... 
    int GetTplLSize() const { return sampleDim[1]; } 
    // ... 
}; 

o, se ti ostini a dichiarazione separata e la definizione:


class NeedleUSsim 
{ 
    // ... 
    int GetTplLSize() const; 
    // ... 
}; 

inline int NeedleUSsim::GetTplLSize() const 
{ return sampleDim[1]; } 

La definizione deve essere visibile in ogni unità di traduzione che usa quel metodo.

+0

È questo l'unico modo? (Voglio separare separatamente la dichiarazione e l'implementazione per motivi di leggibilità) – stanigator

+1

Fondamentalmente sì. Il compilatore deve conoscere il corpo della funzione durante la compilazione delle chiamate, quindi il corpo deve trovarsi nel file di intestazione incluso. Tuttavia, è possibile dichiarare semplicemente la funzione nella dichiarazione della classe e aggiungere l'implementazione in un secondo momento nel file di intestazione. – Hans

+0

Vedo. Credo che dovrei vivere con la scrittura del codice in questo modo allora. Grazie per i consigli. – stanigator

2

Se si dispone di una funzione inline, è necessario inserire la definizione nel file di intestazione.

+0

Ho provato a inserire la parola chiave inline nelle definizioni nel file di intestazione e ho ancora lo stesso errore del linker. – stanigator

+2

Non solo la parola chiave inline, l'intera definizione dovrebbe andare nel file di intestazione. Quindi, spostalo dal tuo file .cpp nel file .h. – ChrisInEdmonton

+1

Definizione, non dichiarazione. –

17

da C++ FAQ Lite

Se si mette la definizione della funzione inline in un file cpp, e se viene chiamato da un altro file cpp, si otterrà un "esterno non risolto "Errore dal linker.

How do you tell the compiler to make a member function inline?

+0

sfortunatamente, come ho appena scoperto nel modo più difficile, questo NON è il caso in MSVC 2013 e 2015. Avevo un in linea in un file CPP (in una libreria) e il suo codice è stato chiamato da un codice sorgente CPP completamente diverso che ha una propria linea con lo stesso nome (ma un codice leggermente diverso, quindi il risultato ha infranto i test). Considero un bug in quell'ambiente di sviluppo. Difficile da trovare... – chksr

3

Come altri hanno già fatto notare, è necessario spostare la definizione della funzione inline al file di intestazione, in questo modo:

class NeedleUSsim 
{ 
    // ... 
    inline int GetTplLSize() { return sampleDim[1]; } 
    // ... 
}; 

La ragione di ciò è che il il compilatore deve sapere quale codice deve essere in linea quando vede una chiamata alla funzione inline. Se si lascia la definizione della funzione nel file .cpp per la classe NeedleUSsim, il codice che il compilatore genera per esso viene intrappolato nel file oggetto NeedleUSsim. Poiché il compilatore legge solo il codice sorgente — non fa mai capolino nel file oggetto di un'altra classe —, semplicemente non ha modo di sapere con quale codice sostituire una chiamata quando sta compilando un altro file .cpp.

0

Vedere Inline Guard Macro idiom. Questo ti permetterà almeno di separare, anche se leggermente, il codice dalla dichiarazione. Consente inoltre di attivare l'inlining delle funzioni tramite define.