c++ - 指向多态类层次结构中派生类型的智能指针,编译错误

标签 c++ compiler-errors polymorphism c++17 smart-pointers

考虑我的类接口(interface)的以下框架。我介绍两种情况,一种使用 shared_ptr<T>另一个使用 unique_ptr<T> .可实例化的用户定义类型是非模板。只有基本构造函数是模板化的,因为它需要知道派生类型才能存储指向它的指针。我没有展示用于检查模板参数是否是父类的派生类型的标准库,以使代码更简单、更易于阅读。

class Foo;

template<typename DerivedType>
class Base {
protected:
    std::shared_ptr<DerivedType> derived_ptr_{nullptr};
    Foo internal_object_{};
public:
    virtual ~Base() {};

    std::shard_ptr<DerivedType> derived_ptr() { return derived_ptr_; }
    Foo* { return &internal_object_; }

    virtual void initialize(/*.../*) = 0;
    virtual void create(/*...*/) = 0;
    virtual void copyTo(/*...*/) = 0;
    virtual void update(/*...*/) = 0;
    virtual void cleanup() = 0;

protected:
    Base() = default;
};


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

    virtual void initialize(/*.../*) override {/*...*/};
    virtual void create(/*...*/) override{
        /*...*/

        // After all creation is successful!
        derived_ptr_ = std::make_shared<Derived>(*this);
    };

    virtual void copyTo(/*...*/) override{/*...*/};
    virtual void update(/*...*/) override{/*...*/};
    virtual void cleanup() override{/*...*};
}

以上编译。我没有测试它的链接或运行时,但它可以编译。

现在让我们考虑情况二,除了 std::shared_ptr<T> 的所有实例之外,一切都与上面完全相同。替换为 std::unqiue_ptr<T>作为基类中的成员变量、getter 以及使用 ptr = std::make_unique<T>(*this) 分配或创建智能指针. std::unique_ptr<T> 的情况除外在 Visual Studio 2017 中编译,编译器语言标志设置为 /std:c++latest生成此编译器错误:

注: -- 我项目中的类名分别是Buffer和VertexBuffer。这是与您从上面的示例中看到的唯一主要区别之一。为了简单起见,我将它们从 namespace 中取出。我还删除了对模板参数的检查,以确保其参数类型是基类的派生类型。
1>------ Build started: Project: Force Engine, Configuration: Debug x64 ------
1>Buffer.cpp
1>c:\users\..\buffer.h(62): error C2440: '<function-style-cast>': cannot convert from 'VertexBuffer' to 'std::unique_ptr<BufferClassType,std::default_delete<_Ty>>'
1>        with
1>        [
1>            BufferClassType=VertexBuffer,
1>            _Ty=VertexBuffer
1>        ]
1>c:\users\...\buffer.h(62): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>Done building project "Force Engine.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我很好奇为什么它在 std::shared_ptr<T> 的情况下编译但在 std::unique_ptr<T> 的情况下编译失败.是什么导致它失败,如何解决这个问题,有没有办法解决这个问题。我知道我可以使用 std::shared_ptr并将其传递回需要它的调用者,但我并不特别想要此指针的“引用”计数。我希望父类(拥有)派生类的指针,同时提供一个接口(interface)以允许外部调用者访问它。在观察者的上下文中或可以选择创建自己的指针,但永远不会成为对象的所有者。包含派生类实例的一个或多个类将拥有派生类本身,但不拥有其内部指针。此编译器错误是否与 unique_ptr 相关? s不能复制之类的?

最佳答案

std::make_unique<Derived>(*this)尝试复制构造 Derived 的实例.但是Derived不可复制,因为它的基类 Base<Derived>不可复制,因为它的数据成员 std::unique_ptr<DerivedType> derived_ptr_不可复制,因为 std::unique_ptr不可复制。

shared_ptr ,一切都是可复制的,代码有效。

关于c++ - 指向多态类层次结构中派生类型的智能指针,编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61443282/

相关文章:

C++ 共享库 : Creation and usage

c++ - CreateEventW 意外失败

java - 如何对变量使用 unicode 转义序列?

c# - “委托(delegate) 'System.Action' 不接受 0 个参数。”这是 C# 编译器错误(lambdas + 两个项目)吗?

haskell - 读取并表示指定要使用的数据类型的输入

c++ - 实现后期多态性的最佳方式

generics - 为什么 `&(?Sized + Trait)`无法转换为 `&dyn Trait`?

c++ - 循环进度指示

C++ 变量检查

C-在 if-else if 部分的赋值中得到不兼容的类型