通常,在头文件中声明成员函数并使用源文件来实现它。我理解的原因是函数实现只驻留在一个转换单元中,并且只链接到其他单元(没有重复的代码),它还允许分离接口和实现,并且不需要转发声明函数相互依赖。
但是,模板中的成员函数取决于模板参数,如果将实现放在源文件中,则无法知道。但是,仍然可以在类之外定义这样的函数,但它的主要参数不再适用。
那么,哪个更好?
template <class T>
class A
{
T m()
{
return T();
}
};
或
template <class T>
class A
{
T m();
};
template <class T>
T A::m()
{
return T();
}
这两段代码如果是inline T A::m()
则相同,但没有它会有什么区别吗?如果功能是虚拟的怎么办?它只是编码风格的问题,还是有不同的语义?如果函数足够大,它会阻止重复的代码,还是编译器足够智能,如果它不会带来任何好处,不会内联它?
答案 0 :(得分:3)
这两段代码如果是
inline T A::m()
则相同,但没有它会有什么不同吗?
对于模板,成员函数隐含inline
,用于类定义的内部和外部。
如果该功能是虚拟的,该怎么办?
没有任何区别。
这只是编码风格的问题,还是有不同的语义?
主要是风格。但是,它会影响名称查找的工作方式。所以,如果我们稍微修改类定义
template <class T>
class A
{
using foo = T;
foo m();
};
我们无法将外部成员定义为
template <class T>
foo A<T>::m()
{
return T();
}
由于foo
的查找在类定义中没有发生,直到资格A<T>::
之后。我们需要完全限定foo
本身,就像typename A<T>::foo
一样。或者也许使用尾随返回类型。
如果函数足够大,它是否会阻止重复代码,或者编译器是否足够智能,如果它不会带来任何好处就不能内联它?
这两种风格都不应对其产生负面影响。两者都受到实施质量问题的影响。但是,当然,不同的实现可能具有不同的特性。