2009-06-05 2 views
22

Я пытаюсь использовать встроенные функции-члены определенного класса. Например, объявление функции и реализация без встраивания как таковые:inline function linker error

в заголовочном файле:

int GetTplLSize(); 

в файле .cpp:

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

По какой-то причине, если я поставил " inline "в одном из вариантов реализации и декларации, а также в обоих местах, я получаю ошибки компоновщика, как показано:

 
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. 

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

ответ

23

Тогда вам нужно поместить определение функции в заголовок. Самый простой способ намекнуть компилятор для встраиваемого должен включать тело метода в объявлении класса как:


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

или, если вы настаиваете на отдельной декларации и определения:


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

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

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

+0

Это единственный способ? (Я хочу отдельно разделить декларацию и реализацию по соображениям удобочитаемости) – stanigator

+1

В принципе да. Компилятор должен знать тело функции при компиляции вызовов к ней, поэтому тело должно находиться во включенном файле заголовка. Однако вы все равно можете просто объявить функцию в объявлении класса и добавить реализацию в более позднем месте в файле заголовка. – Hans

+0

Я вижу. Наверное, мне просто нужно было бы написать код таким образом. Спасибо за советы. – stanigator

2

Если у вас встроенная функция, вы должны поместить определение в файл заголовка.

+0

Я попытался поставить ключевое слово inline в определениях в файле заголовка, и я все равно получаю ту же ошибку компоновщика. – stanigator

+2

Не только ключевое слово inline, все определение должно идти в файле заголовка. Итак, переместите его из вашего .cpp-файла в ваш .h-файл. – ChrisInEdmonton

+1

Определение, а не декларация. –

17

от C++ FAQ Lite

Если поставить определение в встраиваемую функцию в в файле .cpp, и если он вызывается из другого файла .cpp, вы получите «неразрешенный внешний " Ошибка с компоновщика.

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

+0

, к сожалению, поскольку я только что нашел трудный путь, это не так в MSVC 2013 и 2015 годах. У меня был встроенный в файл CPP (в библиотеке), и его код был вызван из совершенно другого исходного кода CPP, который имеет собственную встроенную строку с тем же именем (но немного другой код, поэтому результат нарушил тесты). Я считаю, что ошибка в этой среде разработки. Трудно найти... – chksr

3

Как и другие уже указывали, что вам нужно, чтобы переместить определение встраиваемой функции в заголовочный файл, например так:

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

Причина этого заключается в том, что компилятор должен знать, какой код встроен, когда он видит вызов встроенной функции. Если вы оставите определение функции в файле .cpp для класса NeedleUSsim, код, созданный для него компилятором, попадает в ловушку в объектном файле NeedleUSsim. Поскольку компилятор только считывает исходный код —, он никогда не заглядывает в объектный файл другого класса —, он просто не знает, с каким кодом заменить вызов, когда он компилирует другой .cpp-файл.

0

См. Inline Guard Macro idiom. Это, по крайней мере, позволит вам отделить, хотя и немного, код от декларации. Он также позволяет переключать встраивание функций через define.