5

Well I'm getting a linker (unresolved external symbol) error when doing the following:

-I have a class "Object" - it is defined in "object.h".

it has a constructor like: explicit Object(double x, /* lots more */);

in file "object.cpp" I want to give that constructor a body: Object::object(double x) : _x(x) {}

This works.. However if I add the keyword "inline" in the "object.cpp" file:

inline Object::Object(double x) : _x(x) {}

suddenly a linker error pops up! "error LNK2019: unresolved external symbol"

Why? - does it mean I can't use inlining with constructors?

EDIT: actually I notice it is the case for all methods. However if I move all methods to the object.h header fil it DOES work. You can't inline function from outside the header file where the object is defined?

EDIT2: alright a big update, I decided to build a quick test case:
main.cpp:

#include "a.h"
int main ()
{
    a t;
    t.test(5);
    return 0;
}

a.h

class a {
public:
    void test (int x);
};

a.cpp

#include <iostream>
#include "a.h"
inline void a::test(int x) {
    std::cout << x << std::endl;
}

This gives the following error:

main.obj : error LNK2019: unresolved external symbol "public: void __thiscall a::test(int)" (?test@a@@QAEXH@Z) referenced in function _main

Removal of the "inline" keyword makes the program work.. As does combining "a.h" and "a.cpp" into 1 file.

I really can't think of more information to give :/

paul23
  • 8,799
  • 12
  • 66
  • 149
  • Take a look at this discussion of inline class member functions - it might help you to understand why one or other case is failing. http://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx – Steve Townsend Nov 18 '10 at 23:40
  • I don't think that `inline` means what you think it means. Can you say why you are trying to achieve with it? – CB Bailey Nov 19 '10 at 00:12

3 Answers3

4

You need to understand the rules about definitions for functions marked inline.

Marking a function inline means that you can define the function in more than one translation unit in your program (but just once per translation unit) but all definitions must be the same and you must provide a definition in every translation unit in which the function is used.

In your example the translation unit from main.cpp uses a::test(int) but there is no definition in that translation unit. There is a definition in the translation unit from a.cpp but here it is marked inline which means that you can't leave a definition out of the translation unit from main.cpp.

I'm not sure why you want to add inline to the definition in a.cpp because it is not necessary or useful. inline allows you to place function definitions in shared header files but it has no use if you want to put the function in a source file.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • I've always heard that for "basic" function (such as "get" to get an internal variable) it improves both speed & memory? – paul23 Nov 19 '10 at 00:15
  • @paul23: In most modern environments compilers will consider inlining any function - whether marked `inline` or not - and with link time code generation even if they are defined in different source files. `inline` just allows you to place those function in places that are (historically) easier for compilers to inline, i.e. header files. It doesn't make any guarantees about which calls are actually inlined. – CB Bailey Nov 19 '10 at 00:29
  • I still don't get it. Other Stackoverflow answer clearly suggest that the declaration should be done in the header file, and the class method implementation should be preceder by the `inline` keyword, as OP did here. Example - http://stackoverflow.com/a/953731/1469954. Then why it is failing? Can you a bit more clear on te translation unit thingy? – SexyBeast Jan 13 '15 at 18:24
  • I used the refactoring function of VS2017 to move the functions from the .h to the .cpp file. VS2017 added the "inline" keyword by itself. What confused me, was that only functions that take arguments made the linker complain for LNK2019. Functions like a(void) were linked Ok. Manually removing the "inline" fixed the problem as you described. – Mike Jun 20 '18 at 15:17
2

You have a lower-case o in the constructor name in the code, whether inline or not. C++ names are case-sensitive.

Try this:

inline Object::Object(double x) : _x(x) {}

I'm not clear what you mean by the /* lots more */ comment in the code you posted. if you have other parameters in this declaration, the constructor's definition has to match that.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
0

There is something incongruent in implementation. If this code is wrote inside class definition, then you don't need "Object::". Sometimes this could cause compiler errors. Just erase it and try again. If is wrote out of class definition, you can not declare inline here.

amald2
  • 1