Reputation: 624
I have a problem, may be dumb.
The thing is, I am unable to inline a constructor in a class.
Consider I have a class called Foo.
If I write the implementation of Foo something like this:
class Foo {
int p;
public:
Foo() { p = 1; }
};
or even like this:
class Foo {
int p;
public:
Foo();
};
inline Foo::Foo() {
p = 1;
}
The program won't compile.
I use the class using the standard method:
Foo obj;
Now when I run g++ main.cpp foo.cpp, I get:
/tmp/ccyVtxvp.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `Foo::Foo()'
collect2: ld returned 1 exit status
At the same time, when I use the same code, after compiling the class as a shared library (with factory functions to return object pointer), it works properly.
Any guesses why this is happening?
Upvotes: 2
Views: 2110
Reputation:
I) When directly building the object, the compiler tries to minimize the work and the object size. Here are the steps the compiler takes:
1) Compile main.cpp. Encounters a call to Foo. At this time, compiler JUST checks the declaration of Foo. The declaration is not inline, hence it adds a function call to Foo in the code.
2) Compiles file.cpp (file containing your class definition). Note that inline functions are NOT compiled (rightly so). They are just expanded to code wherever the function is called (provided the definition is available in that file).
3) Now, when it tries to link, it does not find the definition of Foo.
II) When building as a library, compiler will compile all associated functions. (you can very well guess why). Hence the linking goes through.
I am sure you know how to solve the problem yourself:
class Foo {
int p;
public:
inline Foo() { p = 1; };
};
but assume you were just wondering why the different behaviour in direct object creation vs building a library.
Upvotes: 0
Reputation: 12212
The problem is this one:
/tmp/ccyVtxvp.o: In function
main': main.cpp:(.text+0x17): undefined reference to
Foo::Foo()' collect2: ld returned 1 exit status
I infer that you have the class defined in foo.cpp, and you're trying to use it in main.cpp. As others have said, C++ don't know how to use Foo, or even its existence, if you don't declare it previously. Module management in C++ is quite complex, and primitive. You're maybe biased by other more modern programming languages such as C# or Java.
Create foo.h:
// foo.h
class Foo:
int p;
public:
Foo() { p = 1; }
};
All the methods you define in the class declaration are automatically considered inline. As a dumb rule, you should create a .cpp file (foo.cpp) matching each declaration or interface file (foo.h). In this case, it is fruitless, since your complete class lies in the interface file. Bur probably your class will grow in complexity, and eventually you'll need to have a method definition in your cpp. So:
Create foo.cpp:
// foo.cpp
#include "foo.h"
Now, in main.cpp you can use Foo, by including its declaration. This is mandatory in C++:
Create main.cpp:
// main.cpp
#include "foo.h"
#include <cstdlib>
#include <cstdio>
int main()
{
Foo f;
std::printf( "Foo was created\n" );
return EXIT_SUCCESS;
}
Upvotes: 0
Reputation: 38173
Here
inline Foo::Foo() {
p = 1;
}
remove the inline
. Add it in the declaration (in the header)
I'm not sure why this works, but works. I've had the same problem and this solved it.
EDIT: something like this:
class Foo {
int p;
public:
//vvvvvv
inline Foo();
};
Foo::Foo() {
p = 1;
}
Upvotes: 0
Reputation: 42805
My guess is that something is taking the address of Foo::Foo()
. This will cause the compiler to expect a non-inlined version to exist somewhere.
Upvotes: 0
Reputation: 133024
Inline functions must be defined in every source file in which they are used. The easiest way to achieve this is to put the definition(body) of the function in the header file and include the header wherever the function is used
Upvotes: 5
Reputation: 42892
You haven't mentioned what's in the header file and what's in the cpp.
To me this looks like you haven't actually compiled Foo::Foo. This can happen when you use inlines.
Upvotes: 0
Reputation: 64223
Your program compiles, but doesn't link. Most likely you didn't include the object file containing the definition for the Foo class.
Or, if you defined it in a header, you just forward declared it, but didn't include the header.
Upvotes: 1