【问题标题】:const overloading without having to write function twice [duplicate]const重载而不必两次编写函数[重复]
【发布时间】:2012-07-25 18:04:26
【问题描述】:

可能重复:
Elegant solution to duplicate, const and non-const, getters?

假设我有一个 c++ 类,其成员函数为 const 重载,如下所示:

        Type*  DoSomething();
const   Type*  DoSomething() const;

如果这是一个更大、更复杂的成员,如何避免重复编写相同的代码?不能从 const 调用任何非常量函数。并且从非常量调用 const 版本会导致 const 指针必须强制转换为非常量(这有点 imo 的味道)。

【问题讨论】:

  • 演员阵容是 Scott Meyers 在 Effective C++ 中建议的方式,以及在 SO 上对这个问题的各种欺骗。

标签: c++ constants overloading


【解决方案1】:

您可以委托给模板静态成员函数,如下所示:

class Widget
{
    Type member;

    template<typename Result, typename T>
    static Result DoSomethingImpl(T This)
    {
        // all the complexity sits here, calculating offsets into an array, etc
        return &This->member;
    }

public:
            Type*  DoSomething() { return DoSomethingImpl<Type*>(this); }
    const   Type*  DoSomething() const { return DoSomethingImpl<const Type*>(this); }
};

在 C++11 中,您甚至可以摆脱非推断模板参数,使用:

static auto DoSomethingImpl(T This) -> decltype(This->member)

【讨论】:

  • 有趣的转折。我之前没有看到私有方法的模板。
  • 看起来 Steve Jessop 在他的回答 here 中主要描述了这一点,尽管我认为私有静态成员函数更简洁。
  • @Ben 我看不出使用静态成员函数的意义。为什么不使用 const 私有成员函数?
  • @ggg:我认为你没有理解最初的问题。 const 成员函数中member 的类型是什么?
  • @ggg:但是成员不应该从const 成员函数中更改。 mutable 在这里不合适,它只是一个 hack,这个答案干净利落地避免了这个问题。
【解决方案2】:

你做了一次,第二次在类上使用 const 属性,你可以使用const_cast

class Foo
{
          Type*  DoSomething()
  {
    // Lots of stuff
  }
  const   Type*  DoSomething() const
  {
    return const_cast<Foo*>(this)->DoSomething();
  }
}

【讨论】:

  • 问题中描述了这个解决方案(非常正确的注释是const_cast有气味)
  • ...气味被塑造了
【解决方案3】:

使用template method 模式从中提取公共代码。例如。

inline const T* prev(size_t i) const
{
    return &FBuffer[ AdjustIndex(i) ];
}

inline T* prev(size_t i)
{
    return &FBuffer[ AdjustIndex(i) ];
}

inline size_t AdjustIndex( size_t i ) const
{
    return Math::ModInt( static_cast<int>( FHead ) - 1 - i, static_cast<int>( FBuffer.size() ) );
}

这种技术可以应用于许多情况(但不是所有情况,即如果行为显着不同)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    相关资源
    最近更新 更多