【问题标题】:why is the overload resolution wrong here?为什么这里的重载解决方案是错误的?
【发布时间】:2021-11-26 19:11:51
【问题描述】:

假设我们有这个作为我们的设置:

#include <iostream>

class Base {
private:
    int a;
public:
    Base(int a)
        : a(a) {
    }

    virtual void print() = 0;
};

class Child : public Base {
public:

    using Base::Base;

    void print() override {
        //some code
    }
};

class Wrapper {
private:
    void* base_ptr = nullptr;
public:
    Wrapper(void* base_ptr)
        : base_ptr(base_ptr) {
        std::cout << "void* version called\n";
    }

    Wrapper(Base* const& base_ptr)
        : base_ptr(base_ptr) {
        std::cout << "Base*const& version called\n";
    }

};

如果我们执行以下操作:

Child* child_ptr = new Child(1);
Wrapper w(child_ptr);

输出是:

Base*const& version called

这是意料之中且完全正常的。 但如果我们将Wrapper(Base *const&amp;) 更改为Wrapper(Base*&amp;),我们将调用void* 版本:

class Wrapper {
private:
    void* base_ptr = nullptr;
public:
    Wrapper(void* base_ptr)
        : base_ptr(base_ptr) {
        std::cout << "void* version called\n";
    }

    Wrapper(Base*& base_ptr)
        : base_ptr(base_ptr) {
        std::cout << "Base*const& version called\n";
    }

};

int main() {
    Child* child_ptr = new Child(1);
    Wrapper w(child_ptr);
    return 0;
}

对于这个版本,我们得到这个输出:

void* version called

但这是为什么呢? Base*const&amp; 不应该让它也兼容临时对象吗?

【问题讨论】:

    标签: c++ constructor overload-resolution


    【解决方案1】:

    好的。经过一段时间的思考,我想通了。这仅仅是因为在我们尝试调用第二个版本的构造函数时发生了隐式转换,我们将Child* 的类型更改为Base*,因此它不再是LValue,而是变成了RValue,因此它不能绑定到Base*&amp;,如果我们将其签名更改为Base*&amp;&amp;,它会选择这个重载(这是预期的,因为那里发生了隐式转换并使其成为RValue)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-31
      • 2016-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多