- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
请帮助我理解以下行为的根本原因。
在文件 a.cpp
中我有:
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; }
}
在文件 b.cpp
中我有:
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; }
}
我的 main
创建一个 X、一个 Y 并调用它们的 operator():
int main( int argc, char *argv[] )
{
NS::X x;
x();
NS::Y y;
y();
return 0;
}
此程序的输出取决于 a.cpp
还是 b.cpp
首先被编译:在第一种情况下,Obj
来自a.cpp
也在 NS::Y
的构造函数中被实例化,在第二种情况下 Obj
来自 b.cpp
在 NS::X
和 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
在 Linux 或 Visual Studio (2005) 上没有来自链接器的警告。如果我在结构声明之外定义 Obj::pong()
,我会收到一个链接器错误,告诉我 Obj::pong 函数是多重定义的。
我进一步试验了一下,发现原因一定与是否内联有关,因为如果我用-O3编译,每个对象都会使用他自己的翻译单元中的Obj。
那么问题就变成了:在非优化编译过程中,内联函数的第二个定义发生了什么?他们被默默地忽略了吗?
最佳答案
这是未定义的行为:您的类定义定义了相同的类类型,因此它们必须相同。对于链接器,这意味着它可以选择一个任意定义作为发出的定义。
如果你想让它们成为分离的类型,你必须将它们嵌套到一个未命名的命名空间中。这将导致该命名空间中的任何内容对于该翻译单元都是唯一的:
namespace NS {
namespace {
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; }
}
So then the question changes to: what happens to the second definition of the inline function during non-optimized compilation? Are they silently ignored?
是的,对于内联函数(在类定义中定义的函数是内联的,即使没有显式声明为内联),同样的原则适用:它们可以在程序中被定义多次,程序的行为就好像它只是被定义一样一次。对于链接器来说,这意味着它可以丢弃除一个定义之外的所有定义。它选择哪一个是未指定的。
关于c++ - 具有不同内联函数定义的函数对象的实例化取决于链接顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1807523/
我是一名优秀的程序员,十分优秀!