【发布时间】:2010-01-17 13:57:14
【问题描述】:
我有一个难题。假设我有一个模板类:
template <typename ValueT>
class Array
{
public:
typedef ValueT ValueType;
ValueType& GetValue()
{
...
}
};
现在我想定义一个函数,它接收对类的引用并调用函数 GetValue()。我通常考虑以下两种方式:
方法一:
template <typename ValueType>
void DoGetValue(Array<ValueType>& arr)
{
ValueType value = arr.GetValue();
...
}
方法二:
template <typename ArrayType>
void DoGetValue(ArrayType& arr)
{
typename ArrayType::ValueType value = arr.GetValue();
...
}
这两种方法几乎没有区别。即使调用这两个函数看起来也完全一样:
int main()
{
Array<int> arr;
DoGetValue(arr);
}
现在,两者中哪一个是最好的?我能想到一些缺点和优点:
方法 1 优点:
参数是一个真正的类而不是模板,因此用户更容易理解界面 - 参数必须是数组是非常明确的。在方法 2 中,您只能从名称中猜测它。我们在函数中使用 ValueType,这样比隐藏在 Array 中并且必须使用作用域运算符访问时更清晰。
此外,typename 关键字可能会让许多不熟悉模板的程序员感到困惑。
方法 2 优点:
这个函数更“真实”地实现了它的目的。当我想如果它,我真的不需要类是数组。我真正需要的是一个具有 GetValue 方法和 ValueType 类型的类。就这样。也就是说,这种方法更通用。
这种方法对 Array 类的变化也较少依赖。如果Array的模板参数改变了怎么办?为什么它会影响 DoGetValue?它并不关心 Array 是如何定义的。
每次我遇到这种情况时,我都不知道该选择什么。你的选择是什么?
【问题讨论】:
-
为了通用性,我还会考虑“更改”您自己的类的接口并尝试模仿 STL 容器,这样您就可以在 STL 容器上使用自己的函数模板作为奖金 >
value_type而不是ValueType、front或back而不是GetValue(或者可能是at,如果它需要一个职位?)等等...... -
@Matthieu,好点子!这是我应该考虑的事情。我从来没有想过STL模仿的可能性。它确实很有用,甚至可以在代码中提供视觉线索。谢谢。