【问题标题】:c++ what does a dynamic cast of a unique pointer return?c ++唯一指针的动态转换返回什么?
【发布时间】:2022-01-17 03:49:45
【问题描述】:

我正在尝试使用 lambdas 来找到一种方法来查找基类类型的向量中有多少特定的派生类。

std::vector<std::unique_ptr<Account>> openedAccounts;

int countCurrent = std::count_if(openedAccounts.begin(), openedAccounts.end(), 
            [](std::unique_ptr<Account> ptr) { return dynamic_cast<Current&>(*ptr) != nullptr; }); // I will call this for savings as well

帐户是基本抽象类,当前帐户是派生类。

我收到错误no operator != matches these operands". 但是,我认为动态转换可以返回一个空指针。

【问题讨论】:

  • 您正在转换为引用,与指针类型进行比较。引用不能是nullptr
  • 这里的问题是您正在尝试复制unique_ptr。顾名思义,unique_ptr 是独一无二的,你不能复制它。 Lambda 必须是 [](const std::unique_ptr&lt;Account&gt;&amp; ptr)
  • @HattedRooster 那么有什么办法呢?
  • @MarekR 不是这样
  • 只需投射到一个指针并从那里检查。

标签: c++ pointers polymorphism smart-pointers dynamic-cast


【解决方案1】:
std::vector<std::unique_ptr<Account>> openedAccounts;

int countCurrent = std::count_if(openedAccounts.begin(), openedAccounts.end(), 
            [](std::unique_ptr<Account> ptr) { return dynamic_cast<Current&>(*ptr) != nullptr; }); // I will call this for savings as well

我在这段代码中看到了 3 个问题:

  1. dynamic_cast&lt;Current&amp;&gt; ... != nullptr - dynamic_cast 为引用抛出异常并且永远不会返回 null_ptr
  2. Lambda 不正确,因为参数 std::unique_ptr&lt;Account&gt; 试图创建应该是唯一的东西的副本。
  3. 如果您有指向某个抽象的指针容器并且您必须执行dynamic_cast,那么这清楚地表明使用的抽象无效。

所以这应该看起来更像这样:

class Account {
public:
    virtual bool isCurrent() { return false; }
    ....
};

std::vector<std::unique_ptr<Account>> openedAccounts;

int countCurrent = std::count_if(openedAccounts.begin(), openedAccounts.end(), 
            [](const std::unique_ptr<Account>& ptr) { return ptr->isCurrent(); });

我不明白最后一点很难处理,所以这里是 hacky 修复:

int countCurrent = std::count_if(openedAccounts.begin(), openedAccounts.end(), 
            [](const std::unique_ptr<Account>& ptr) { return dynamic_cast<Current *>(ptr.get()) != nullptr; });

【讨论】:

  • @谢谢,但您的第一个解决方案是更好的方法吗?
  • 一般来说是的,因为第一个代码根本不必使用Current 类型(无依赖性),这是OOP的主要特征。我不知道你的代码的细节,所以我不知道你需要纠正多少东西才能让它工作。
  • 好的,谢谢,而且对于虚拟布尔,将其设为纯虚拟不是最好的吗?并在我当前的储蓄课程中覆盖它?
【解决方案2】:

我认为动态转换可以返回一个空指针。

仅当您动态转换为指针类型时。

引用没有 null 的表示。当您动态转换为引用类型时,如果指针转换返回 null,则会引发异常。

那该怎么办呢?

dynamic_cast<Current*>(ptr.get())

会起作用的。但是,需要dynamic_cast 的设计通常可能很糟糕。 dynamic_cast 主要用于解决设计不良的 API。

我建议考虑替代设计。

【讨论】:

  • 我没有使用任何 API,只是一个简单的基于控制台的银行系统,我需要找到一种方法来查找基类型向量中有多少派生类对象。
  • 您能否进一步扩展,因为我也在尝试理解 lambdas 是否可以使用 lambdas 来做到这一点?
  • @paigelarry342 Lambda 没有继承层次结构。我不明白它们与您的问题有何关系。
  • @paigelarry342 typeid 的建议很糟糕。我没听懂你先说什么。
  • 好的,但是 type_id 如何解决我的问题?你能解释一下吗
【解决方案3】:

动态转换完全返回您所要求的内容。

您要求提供Current&amp; 或当前参考。

你可能想问这个

return dynamic_cast<Current*>(ptr.get()) != nullptr; 

【讨论】:

  • 谢谢,它现在摆脱了我的错误!我的其余代码看起来还可以吗?
  • 看了一眼,是的。
猜你喜欢
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2017-11-10
相关资源
最近更新 更多