Hi all,
Please help me understand the root cause of the following behaviour.
In file a.cpp
I have:
namespace NS {
struct Obj {
void pong(){ cout << "X in "__FILE__ << endl; }
double k;
};
X::X() { Obj obj; obj.pong(); }
void X::operator()() { cout << "X says hello" << endl; }
}
In file b.cpp
I have:
namespace NS {
struct Obj {
void pong(){ cout << "Y in "__FILE__ << endl; }
bool m;
};
Y::Y() { Obj obj; obj.pong(); }
void Y::operator()() { cout << "Y says hello" << endl; }
}
My main
creates an X, an Y and calls their operator()s:
int main( int argc, char *argv[] )
{
NS::X x;
x();
NS::Y y;
y();
return 0;
}
The output of this program depends on whether a.cpp
or b.cpp
gets compiled first: in the first case the Obj
from a.cpp
is instantiated also within NS::Y
's constructor, in the second case the Obj
from b.cpp
is instantiated in both NS::X
and NS::Y
.
% g++ b.cpp a.cpp main.cpp
% ./a.out
X in a.cpp
X says hello
Y in b.cpp
Y says hello
% g++ b.cpp a.cpp main.cpp
% ./a.out
Y in b.cpp
X says hello
Y in b.cpp
Y says hello
No warnings from the linker either on Linux or Visual Studio (2005). If I define Obj::pong()
outside the declaration of the struct I get a linker error telling me that the Obj::pong function is multiply defined.
I experimented a bit further and found out that the cause must be related to whether or not the inlining, because if I compile with -O3, the each object uses the Obj from his own translation unit.
So then the question changes to: what happens to the second definition of the inline function during non-optimized compilation? Are they silently ignored?