【问题标题】:About `std::unique_prt<Base>& pBase= make_unique<Derived>();`关于`std::unique_prt<Base>& pBase= make_unique<Derived>();`
【发布时间】:2020-09-19 20:29:14
【问题描述】:

第一段代码不能编译,而第二段代码可以。为什么?

代码确实几乎相同。 如果能在这个问题上得到一些帮助,我将不胜感激。

下面的代码无法编译。您可以在http://cpp.sh/8j53y 上查看。

dynamic_cast
#include <iostream>
#include <memory>

using namespace std;

class Derived;

class Base { 
public:
    static unique_ptr<Base>& get_instance()
    {
        pBase = make_unique<Derived>();
        return pBase;
    }

private:
    static unique_ptr<Base> pBase;
};

class Derived: public Base { };

std::unique_ptr<Base> Base::pBase = nullptr;

int main () {

    auto& instance = Base::get_instance();
    return 0;
}

下面的代码可以编译。

#include <iostream>
#include <memory>

using namespace std;

class Derived;

class Base { 
public:
    static unique_ptr<Base>& get_instance();

private:
    static unique_ptr<Base> pBase;
};

class Derived: public Base { };

std::unique_ptr<Base> Base::pBase = nullptr;

unique_ptr<Base>& Base::get_instance()
{
     pBase = make_unique<Derived>();
     return pBase;
}

int main () {
    auto& instance =  Base::get_instance();
    return 0;
}

【问题讨论】:

  • 我假设 auto Base::get_instance(); 应该是 auto instance = Base::get_instance(); - 不是它会编译,但问题不会是与错字相关的问题
  • 这很重要。链接过时了,我个人一开始就无法打开您的链接。一个问题必须是自包含的。它必须包含您询问的正确代码,没有其他问题(以及错误消息)。您正在请求志愿者来帮助您。不要轻率地对待他们的时间。
  • 很抱歉打扰您。我会听从您的建议。今天的网站有些不稳定。
  • 旁白:将你的单身人士放在unique_ptr 中有什么意义?您真的打算让调用者能够重置该指针吗?
  • 这只是整个项目的一部分。我部分同意你的观点。我们假设调用者不会重置那个指针,那么真的没有必要使用unique_ptr吗?

标签: c++ c++11 inheritance c++17 unique-ptr


【解决方案1】:

当您定义 Base::get_instance 内联时,Derived 还没有定义(只有前向声明)。因此,它无法将std::unique_ptr&lt;Derived&gt; 转换为std::unique_ptr&lt;Base&gt;,因为尚未看到Derived 继承自Base 的定义。出于同样的原因,std::make_unique&lt;Derived&gt;() 也会失败,因为Derived 还没有定义。

这就是为什么你需要在定义Derived之后再定义Base::get_instance来编译。您可以将其标记为inline,然后将其定义在一个头文件中:

class Base { 
public:
    static unique_ptr<Base>& get_instance();

private:
    static unique_ptr<Base> pBase;
};

class Derived: public Base { };

/*
`inline` here so the definition can appear in multiple translation units
(e.g., directly in the header file)
*/
inline unique_ptr<Base>& Base::get_instance()
{
     pBase = make_unique<Derived>();
     return pBase;
}

【讨论】:

  • 不过,我会将inline 移至定义中。 inlinedefinition 从 ODR 中排除,因此将其放在 declaration 上虽然有效,但具有误导性,因为它不会以任何有意义的方式影响声明。 (这是一个不属于类接口的实现细节。)
  • 什么是“ODR”的缩写?
  • @Artyer 我同意你的观点。但我还是想深入挖掘。你看,所有的代码都可以被编译器看到,那为什么它不开始编译std::unique_prt&lt;Base&gt;&amp; pBase= make_unique&lt;Derived&gt;();整个文件都分析过了。我觉得没那么难。你觉得呢?
  • @sunshilong369 请参阅stackoverflow.com/q/19630570/5754656 了解 ODR 是什么(在这种情况下,当您在类中编写函数体时,有一个隐含的 inline,它可以让您多次编写相同的定义当它是#included)。该函数需要在它出现时立即实例化,而不是在分析文件时。如果你有类似class Derived : public std::conditional_t&lt;can_assign_derived_ptr_to_base, NotBase, Base&gt; {} 的东西怎么办?那么你只能分配它,如果你不能分配它。这就是为什么看到它就会被编译的原因之一
  • 感谢您的澄清。抱歉,我无法理解您的示例。您能否更详细地解释一下?“那么您只能在无法分配的情况下分配它”是什么意思?
猜你喜欢
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 2017-08-22
  • 2017-08-06
  • 2020-02-09
  • 2023-02-07
相关资源
最近更新 更多