由于超类(传递值)导致重载构造函数的模糊调用

Ber*_*fer 5 c++ overload-resolution

我在GSL的某些部分写了一个小的C++包装器,遇到了下面的谜题(对我来说).代码(简称其基本内容)如下:

    #include <stdlib.h>
    struct gsl_vector_view {};

    class Vector : protected gsl_vector_view {
            public:
            Vector ( const Vector& original );
            Vector ( const gsl_vector_view view );
    };

    class AutoVector : public Vector {
            public:
            explicit AutoVector ( const size_t dims );
    };

    void useVector ( const Vector b ) {}

    void test () {
            const AutoVector ov( 2 );
            useVector( ov );
    }
Run Code Online (Sandbox Code Playgroud)

不会使用gcc 4.4.5 g ++ -c v.cpp编译但是yield

     In function ‘void test()’:
    19: error: call of overloaded ‘Vector(const AutoVector&)’ is ambiguous
    7: note: candidates are: Vector::Vector(gsl_vector_view)
    6: note:                 Vector::Vector(const Vector&)
    19: error:   initializing argument 1 of ‘void useVector(Vector)’
Run Code Online (Sandbox Code Playgroud)

我很惊讶通过调用useVector(Vector)来考虑受保护的基类gsl_vector_view.我原以为useVector属于"The C++ Programming Language",第3页,第3页中的"普通大众".405因此无法访问受保护的信息,因此不能被它混淆.我知道通过将构造函数声明为可以消除歧义

    explicit Vector ( const gsl_vector_view view );
Run Code Online (Sandbox Code Playgroud)

我不知道(而且,老实说,也不明白),当我将构造函数声明为as时,重载调用的模糊性消失了

    Vector ( const gsl_vector_view& view );
Run Code Online (Sandbox Code Playgroud)

即通过引用传递参数(无论如何我会考虑正确的做事方式).

wil*_*ilx 4

重载解析是在访问检查之前完成的,这就是为什么甚至考虑受保护的基类的成员。

标准第 13.3 章描述了过载解决方案。我的解释是绑定const AutoVector ovVector ( const Vector& original );用户定义的 conversion,一种派生到基的转换([13.3.3.1.4/1]) 类型。对于Vector ( const gsl_vector_view view );,转换序列也是用户定义的转换,因为它是左值到右值的转换,然后是用户定义的转换。因此,两个转换序列被认为是相等的,没有一个比另一个更好,因此你会得到歧义。

现在,如果将 ctor 更改为Vector ( const gsl_vector_view& view );,则两种转换都是左值到值转换,然后是用户定义的转换(派生到基转换)。这两个可以排序([13.3.3.2/4])并且转换到const Vector&被认为更好,因此不存在歧义。