5

可能的重复:
如何删除相似的 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 的类型转换。

编辑:所以我想打电话给另一个成员以避免代码重复。

4

6 回答 6

2

[注意更正;很抱歉最初弄错了。]

这是使用 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++中甚至有一章专门介绍了这种技术。

于 2013-01-18T14:33:24.930 回答
1

您可以执行以下操作:

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]]); }
};

我不确定在这种情况下是否真的值得付出努力,但如果可能重复的代码变得更加复杂,这可能会很有用。

于 2013-01-18T14:36:38.100 回答
1

您可以通过一些模板元编程来避免 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); }
于 2013-01-18T15:05:34.510 回答
0

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

于 2013-01-18T14:48:35.417 回答
0

怎么样

const A &B::GetA (int index) const
{
    return *(const_cast<B*>(this)->GetA(index));
}
于 2013-01-18T14:31:05.060 回答
0

IMO 这不是足够的代码(或复杂性)值得去重复。

正如您在两个const_cast基于 - 的解决方案中看到的那样,强制转换表达式实际上原始代码长。

但是,如果你有一个更长或更复杂的表达你真的很担心,请展示出来。

于 2013-01-18T14:37:18.883 回答