私有和公有运算符重载

3

我尝试使用霍纳法则实现,但遇到了一个问题:

root@host:~# cat | g++ -x c++ -std=gnu++11 - && ./a.out
#include <iostream>
#include <iomanip>
#include <iterator>
#include <vector>
#include <numeric>
#include <algorithm>
#include <random>
#include <chrono>

#include <cstdlib>

template< typename F >
class horner
{
public :

    typedef std::vector< F > V;

    horner(F const & x_, V const & c_)
        : x(x_)
        , c(c_)
        , y(0.0L)
    { ; }

    operator F const () const
    {
        return std::accumulate(c.rbegin(), c.rend(), *this).y;
    }

private :

    friend horner std::accumulate< typename V::const_reverse_iterator, horner >(typename V::const_reverse_iterator, typename V::const_reverse_iterator, horner);

    void operator = (F const & rhs)
    {
        y = rhs;
    }

    operator F ()
    {
        y *= x;
        return y;
    }

    F const & x;
    V const & c;
    F y;

};

#define N_COEFF_PARABOLA 3

int main()
{
    typedef double F;
    typedef typename horner< F >::V V;

    V c;
    unsigned seed(std::chrono::system_clock::now().time_since_epoch().count());
    std::cout << "seed = 0x"
              << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(seed) * 2)
              << seed << std::endl;
    std::mt19937 generator(seed);
    std::generate_n(std::back_inserter(c), N_COEFF_PARABOLA, generator);

    std::cout << "coefficients: ";
    std::copy(c.begin(), c.end(), std::ostream_iterator< F >(std::cout, " "));
    std::cout << ';' << std::endl;

    F const x(generator());
    F const y(horner< F >(x, c));
    std::cout << "y(" << x << ") = " << y << std::endl;

    // naive
    F xx(1.0L);
    F yy(0.0L);
    for (typename V::size_type i(0); i < c.size(); ++i) {
        yy += c[i] * xx;
        xx *= x;
    }
    std::cout << "y'(" << x << ") = " << yy << std::endl;

    return EXIT_SUCCESS;
}
// press ^D

<stdin>: In function ‘int main()’:
<stdin>:39:5: error: ‘horner<F>::operator F() [with F = double]’ is private
<stdin>:71:32: error: within this context
root@host:~#

在我看来,这个问题不应该出现,因为main()只会看到类型强制转换运算符的operator F const & () const版本。但是出现了问题。
那么出现错误的原因是什么?

7
重载决议不关心访问说明符。 - R. Martinho Fernandes
4
确实,因为它们不是方法签名的一部分。 - Yam Marcovic
1个回答

4

在C++中,可见性和可访问性的概念是完全正交的。如果一个方法是可见的,但不可访问,编译器可能会在重载分辨率时选择它并产生一个硬错误,因为它不能使用它。这是有意为之的,以防止代码在获得或失去访问权限时悄然改变语义。


最近我遇到了这个问题,让我感到非常沮丧。我只想让一个重载的变量可以私有访问(这样它就可以提供非const引用),而另一个重载的变量则是公共的const(这样公共代码就不能更改引用)。为什么不允许这样做呢? - Tynach
@Tynach,因为如果允许这样做,你会使用它,然后两年后你会想知道为什么相同类型的参数和相同函数在被同一类的另一个方法调用或从该类外部的代码调用时表现不同。 - Jan Hudec
1
那时,我会查看头文件并看到两个声明是公共/私有的,然后我就已经得到了答案。对我来说,这是一个很差的借口。 - Tynach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接