我有两个动态库和一个可执行文件:
作为查看特定函数何时被调用的测试,我在 libOtherLibrary.so 的内联函数中添加了一个print语句(代码详细信息无关紧要) :
template<class T>
inline void className<T>::clear() const
{
Info << "Hello World!" << endl; // My message!
if (isTmp() && ptr_)
{
if (ptr_->unique())
{
delete ptr_;
ptr_ = 0;
}
else
{
ptr_->operator--();
ptr_ = 0;
}
}
}
然后我重新编译了 libOtherLibrary.so ,然后重新编译 libMyLibrary.so 。最后我重新链接(所以没有重新编译) exe 。
结果是,在 libMyLibrary.so 中启动的对className<T>::clear()
的任何调用都使用了此内联方法的旧实现,而对{{1由 libOtherLibrary 启动.so使用 new 实现。
当我决定重新编译 exe (然后链接它)时,结果是始终使用 new 实现。
我的问题是:有人可以向我解释为什么 exe 需要重新编译,而不是只重新链接?
也就是说,在 libMyLibrary.so 的编译阶段,应该发生 libOtherLibrary.so 的函数className<T>::clear()
的内联,不是吗?毕竟,它是 libMyLibrary.so 中包含的函数,它调用className<T>::clear()
。然后我希望链接 exe 就足够了,因为 exe 不会调用这个特定的内联函数。单独的链接器将处理任何改变的ABI兼容性。
答案 0 :(得分:2)
我的问题是:有人可以向我解释为什么需要exe 重新编译,而不是只重新链接?
因为,对于您的特定用例,如果没有它,您将会产生ODR violation的愤怒。
结果是对
className<T>::clear()
的任何调用均已启动 libMyLibrary.so 使用了此内联方法的旧实现,而对className<T>::clear()
的任何调用均由 libOtherLibrary .so使用 new 实现。
如果您有功能模板,请说:
template<class T>
inline void className<T>::clear(){
....
}
在多个翻译单元(.cpp文件)中为ODR used。它的实例化将在每个这样的翻译单元中定义,因为 function-templates 是隐含的inline
。
此处列出了此类多重定义的规则basic.def.odr/6。列出的要求之一指出 &#34; D的每个定义应由相同的令牌序列组成;&#34; 。
修改该功能模板并重新编译一些翻译单元,使ODR使用它,并链接您的程序,而不重新编译所有翻译单元使ODR使用它违反了C ++的神圣的一个定义规则
不需要编译器工具链来诊断它。
答案 1 :(得分:0)