我有两个成员
A &B::GetA (int i)
{
return *(m_C[m_AtoC[i]]);
}
const A &B::GetA (int i) const
{
return *(m_C[m_AtoC[i]]);
}
现在我只是复制代码,但可能存在很好的方法来做到这一点。我当然不想处理从 const 到非 const 的类型转换。
编辑:所以我想打电话给另一个成员以避免代码重复。
我有两个成员
A &B::GetA (int i)
{
return *(m_C[m_AtoC[i]]);
}
const A &B::GetA (int i) const
{
return *(m_C[m_AtoC[i]]);
}
现在我只是复制代码,但可能存在很好的方法来做到这一点。我当然不想处理从 const 到非 const 的类型转换。
编辑:所以我想打电话给另一个成员以避免代码重复。
[注意更正;很抱歉最初弄错了。]
这是使用 a 的合适情况const_cast
,它允许您通过将非常量函数的调用转发到相应的 const 函数来删除重复代码:
A & B::GetA(int index)
{
return const_cast<A &>(static_cast<B const *>(this)->GetA(index));
}
重要的是要注意,这只能在一个方向上完成:您可以non-const
根据常量实现该方法,但不能反过来:常量调用GetA()
获取对相关对象的常量引用,但是由于我们有额外的信息表明改变对象实际上是可以的,我们可以安全地从结果中去掉常量。
在 Scott Meyer 的Effective C++中甚至有一章专门介绍了这种技术。
您可以执行以下操作:
class B {
public:
A& GetA (int index) { return GetA_impl(index); }
const A& GetA (int index) const { return GetA_impl(index); }
private:
A& GetA_impl (int index) const { return *(m_C[m_AtoC[i]]); }
};
我不确定在这种情况下是否真的值得付出努力,但如果可能重复的代码变得更加复杂,这可能会很有用。
您可以通过一些模板元编程来避免 const_cast。
// This meta function returns a const U if T is const, otherwise returns just U.
template <typename T, typename U>
make_same_const<T, U>
{
typedef typename std::conditional<
std::is_const<T>::value,
typename std::add_const<U>::type,
U
>::type type;
};
// Generic version of a function. Constness of return type depends on
// constness of T.
// This is a static member template of B.
template <typename T>
make_same_const<T, A>::type& B::GetA(T& obj, int i)
{
return *(obj.m_C[obj.m_AtoC[i]]);
}
A& B::GetA(int i) { return B::GetA(*this, i); }
A const& B::GetA(int i) const { return B::GetA(*this, i); }
GetA()
假设和的主体GetA() const
是相同的(这意味着GetA()
不修改*this
),您可以安全地使用一个const_cast
来实现使用非 const 的 const 版本:
const A& B::GetA() const {
return const_cast<B*>(this)->GetA();
}
非常量GetA()
不会修改对象,因此在对象上调用它const B
不是未定义的。non-const 返回的非常量引用在从 中返回之前被GetA()
转换为 a ,因此那里也不存在未定义行为的危险。const&
GetA() const
怎么样
const A &B::GetA (int index) const
{
return *(const_cast<B*>(this)->GetA(index));
}
IMO 这不是足够的代码(或复杂性)值得去重复。
正如您在两个const_cast
基于 - 的解决方案中看到的那样,强制转换表达式实际上比原始代码长。
但是,如果你有一个更长或更复杂的表达你真的很担心,请展示出来。