c++ - 由于父类(super class)(按值传递)导致的重载构造函数调用不明确

标签 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 );
    }

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

     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)’

protected 基类 gsl_vector_view 被 useVector(Vector) 的调用考虑到了,我感到很惊讶。我本以为 useVector 属于“The C++ Programming Language”第 3 e.p. 的说法中的“普通大众”。 405,因此无法访问 protected 信息,因此不会被它混淆。 我知道我可以通过将构造函数声明为来消除歧义

    explicit Vector ( const gsl_vector_view view );

我不知道(老实说,也不明白)的是,当我将构造函数声明为时,重​​载调用的歧义消失了

    Vector ( const gsl_vector_view& view );

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

最佳答案

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

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

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

关于c++ - 由于父类(super class)(按值传递)导致的重载构造函数调用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7157691/

相关文章:

c++ - 如何从 Qt4 小部件的文本属性中剥离 HTML?

c# - 方法重载决议系统如何决定在传递空值时调用哪个方法?

c++ - 混淆在右值和左值上重载成员函数

c++ - boost::archive::xml_iarchive 因 xml(反序列化上下文)而失败

c++ - 数组分配下标号

C++ 为有限数量设置的所有变体编译代码

c++ - 使用继承的成员运算符而不是免费的成员运算符

java - TCP Java 客户端向 C++ 服务器发送数据

c++ - 模板重载解析: what happens when multiple templates match?

c++ - 涉及临时对象的运算符重载决策顺序