简体   繁体   English

派生的 class 的智能指针如何隐式转换为基本 class?

[英]How are smart pointers of a derived class implicitly convertible to the base class?

From cppreference ,cppreference

If T is a derived class of some base B , then std::unique_ptr<T> is implicitly convertible to std::unique_ptr<B>如果T是某个基B的派生 class ,则std::unique_ptr<T>可隐式转换为std::unique_ptr<B>

which it obviously must be for polymorphism to work as it does with raw pointers.显然,多态性必须像处理原始指针一样工作。 My question is, if a smart pointer is not generally convertible to a pointer as we can see here , then what is the mechanism used by the smart pointer to allow for runtime polymorphism?我的问题是,如果智能指针通常不能像我们在这里看到的那样转换为指针,那么智能指针使用什么机制来实现运行时多态性? My thinking is that either in a constructor or std::make_unique<>() / std::make_shared<>() the internal pointer in the object is used for this conversion.我的想法是,在构造函数或std::make_unique<>() / std::make_shared<>()中,object 中的内部指针用于此转换。 But if these implicit conversions aren't allowed anywhere else, why don't we have to call get() when constructing our smart pointers?但是,如果在其他任何地方都不允许这些隐式转换,为什么我们在构造智能指针时不必调用 get() 呢?

As a very simple example I came up with the following test:作为一个非常简单的示例,我提出了以下测试:

#include <iostream>
#include <memory>

class Base
{
public:
    virtual ~Base() = default;

    virtual void foo() const { std::cout << "Base foo() called." << std::endl; }
};

class Derived : public Base
{
public:
    virtual void foo() const override { std::cout << "Derived foo() called." << std::endl; }
};

void bar(Base* pBase) 
{
    std::cout << "bar() called." << std::endl;
    pBase->foo();
}

int main()
{
    std::unique_ptr<Base> pObject { std::make_unique<Derived>() };      // Implicit conversion here, why no call to get()?

    // bar(pObject);                                                    // Can't be converted, so we have to call get()
    bar(pObject.get());
}

My question is, if a smart pointer is not generally convertible to a pointer as we can see here, then what is the mechanism used by the smart pointer to allow for runtime polymorphism?我的问题是,如果智能指针通常不能像我们在这里看到的那样转换为指针,那么智能指针使用什么机制来实现运行时多态性?

Smart pointers are explicitly designed to make such conversion possible.智能指针被明确设计为使这种转换成为可能。 As you can see in std::unique_ptr constructors documentation :正如您在std::unique_ptr构造函数 文档中看到的:

template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept; (6)

this overload is created for this purpose.为此目的创建了此重载。

This constructor only participates in overload resolution if all of the following is true:如果以下所有条件都为真,则此构造函数仅参与重载决议:

a) unique_ptr<U, E>::pointer is implicitly convertible to pointer a) unique_ptr<U, E>::pointer 可隐式转换为指针

b) U is not an array type b) U 不是数组类型

c) Either Deleter is a reference type and E is the same type as D, or Deleter is not a reference type and E is implicitly convertible to D c) Deleter 是引用类型并且 E 与 D 的类型相同,或者 Deleter 不是引用类型并且 E 可以隐式转换为 D

emphasis is mine.重点是我的。 So as pointer to derived class is implicitly convertible to base this constructor overload makes such conversion possible.因此,由于指向派生 class 的指针可以隐式转换为基础,因此此构造函数重载使得这种转换成为可能。

The returned pointer from .get() does not transfer ownership to the caller (that would be .release() )..get()返回的指针不会将所有权转移给调用者(即.release() )。

If you use the pointer from .get() to construct another smart-pointer you will get a double-free.如果您使用来自.get()的指针来构造另一个智能指针,您将获得双重释放。

So this is an error:所以这是一个错误:

std::unique_ptr<Base> pObject { std::make_unique<Derived>().get() };

this works这行得通

std::unique_ptr<Base> pObject { std::make_unique<Derived>().release() };

And for shared_ptr constructing from both .get() and .release() is wrong because you could have other instances having the same shared-state that you're not tranferring..get().release()构造shared_ptr是错误的,因为您可能有其他实例具有相同的共享状态,而您没有转移。 So you would potentially end up with two smart-pointers to the same pointer but with a different shared-state.因此,您最终可能会得到两个指向同一个指针但具有不同共享状态的智能指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM