2014-03-04 35 views
3

我读“有效的C++”,并试图从第3条编译这个例子:不能超载独自返回类型来区分功能

class TextBlock 
{ 
public: 
    const char& operator[](size_t position) const 
    { 
     return text[position]; 
    } 
    char& operator[](size_t position) const 
    { 
     return const_cast<char&>(
      static_cast<const TextBlock&>(*this) 
      [position] 
     ); 
    } 
private: 
    string text; 
}; 

此必须说明如何防止重复代码;不写相同的代码来返回非const结果。我正在使用VS2012。但是我收到一个错误。我听说重载的函数不能有不同的返回类型,但看到这个后我不知道该怎么想。

回答

6

我觉得书上说

const char& operator[](size_t position) const 
char& operator[](size_t position) 

const char& operator[](size_t position) const 
char& operator[](size_t position) const <--- extra const here 

cv修饰符是一个函数签名的一部分,返回类型都没有。

+0

是不是也不好的做法,在'string'返回一个字符的参考?似乎堆腐败等待发生 – tenfour

+2

@tenfour不是什么'std :: string :: operator []'做什么? –

+0

谢谢,它的工作很好。 – Anton

3

正如其他人所指出的那样,问题在于您无意中添加了const

但是,更重要的是你给出的例子,来自“ Effective C++ ”教坏事™。

,它与涉及的问题是没有问题的,并将该溶液,表达在const方法方面的非const方法,通过石膏,是所厌恶的。

与此同时,没有处理真正的问题(例如调试的简易性,检查参数值,在使用前为了可读性而定义)。

这里有更好的和更短的代码:

using Index = ptrdiff_t; 

class TextBlock 
{ 
private: 
    std::string text; 

public: 
    auto operator[](Index const i) const 
     -> char const& 
    { return text[i]; } 

    auto operator[](Index const i) 
     -> char& 
    { return text[i]; } 
}; 

对于您没有,您可以使用此机器支持方便的already- const -paired底层表示的情况下:

template< class A, class B > 
struct With_const_as_T_ { using T = typename std::remove_const<B>::type; }; 

template< class A, class B > 
struct With_const_as_T_< A const, B > { using T = B const; }; 

template< class A, class B > 
using With_const_as_ = typename With_const_as_T_<A, B>::T; 

&hellip;发表在模板功能方面都非constconst,像这样:

class TextBlock 
{ 
private: 
    std::string text; 

    template< class Self > 
    static auto at(Self& self, Index const i) 
     -> With_const_as_<Self, char>& 
    { return self.text[i]; } 

public: 
    auto operator[](Index const i) const 
     -> char const& 
    { return at(*this, i); } 

    auto operator[](Index const i) 
     -> char& 
    { return at(*this, i); }  // Look, no casts! 
}; 
+0

将普通代码合并到一个函数中并避免这种丑陋的表演是一个非常好的主意。但是,这样做有点不同吗?解读发布的例子并不那么容易。 –

+0

非常感谢,这非常有用 – Anton

+0

还有一个问题。如果我的代码包含比返回指针多得多的操作,那么我的代码是否会是一个合适的解 – Anton