【问题标题】:std::shared_ptr of abstract class to instantiate derived class [closed]抽象类的std :: shared_ptr实例化派生类[关闭]
【发布时间】:2014-10-13 19:54:41
【问题描述】:

我正在尝试使用std::shared_ptr,但我不确定是否可以将shared_ptr 用于抽象类并从此智能指针调用派生类。这是我目前拥有的代码

IExecute *ppCIExecuteExecuteOperation = NULL;

for(int i = 0; i < 3; ++i)
{
    switch (stOperationType.key)
    {
        case E_OPERATIONKEY::DrawCircle:
        pCIExecuteExecuteOperation = new CCircle();
        break;
        case E_OPERATIONKEY::DrawSquare:
        pCIExecuteExecuteOperation = new CSquare();
        break;
        case E_OPERATIONKEY::Rhombus:
        pCIExecuteExecuteOperation = new CRehombus();
        break;
        default:
        break;
    }
} 
pCIExecuteExecuteOperation->Draw();

这里IExecute是一个抽象类,CCircle、CSquare、CRhombus是IExecute的派生类。

我只想使用shared_ptr&lt;IEXectue&gt;pCIExecuteExecuteOperation(nullptr) 并在 switch 语句中使其指向派生类之一,我该如何实现?

编辑: 答案是使用 make_shared 或 reset()

谢谢大家,我没想到会这么简单。

【问题讨论】:

  • 你真的尝试过吗?
  • 显而易见的方法应该可行。
  • @Geoffroy:我是 c++ shared_ptr 的新手,浏览了几个站点并且很困惑

标签: c++ inheritance c++11 smart-pointers


【解决方案1】:

这很容易。看代码,感受一下。

std::shared_ptr<IExecute> ppCIExecuteExecuteOperation;

for(int i = 0; i < 3; ++i)
{
    switch (stOperationType.key)
    {
        case E_OPERATIONKEY::DrawCircle:
            pCIExecuteExecuteOperation.reset(new CCircle());
            break;
        case E_OPERATIONKEY::DrawSquare:
            pCIExecuteExecuteOperation.reset(new CSquare());
            break;
        case E_OPERATIONKEY::Rhombus:
            pCIExecuteExecuteOperation.reset(new CRehombus());
            break;
        default:
            break;
    }
} 
pCIExecuteExecuteOperation->Draw();

【讨论】:

  • 使用std::make_shared而不是new在内存泄漏方面不是更安全吗?
  • @evotion 为什么?你能解释一下吗?
  • cppreference 的注释显示了这一点。那么问题是,如果这段代码是一个好的实践,因为没有 make_shared 很难阅读,但它可能会导致问题。
  • @evotion 不,在这种情况下可以直接new。该 cppref 页面的要点与评估顺序有关,但在我的情况下不会发生。
  • 谢谢你们,但我想知道上面代码中提到的使用 std::make_shared 和 "new" 有什么区别
【解决方案2】:

方法std::make_shared&lt;T&gt; 创建一个T 类型的共享指针对象并调用它的构造函数。所以不要打电话给new,而是打电话给std::make_shared

std::shared_ptr<IEXectue>pCIExecuteExecuteOperation(nullptr);
...
...
switch (stOperationType.key)
{
    case E_OPERATIONKEY::DrawCircle:
    pCIExecuteExecuteOperation = std::make_shared<CCircle>();
    break;
    ...

std::make_shared 也可以使用参数,这些参数被转发给构造函数,假设有一个带有该参数列表的构造函数。

【讨论】:

    【解决方案3】:

    线

    IExecute *ppCIExecuteExecuteOperation = NULL;
    

    应该替换为

    std::shared_ptr<IExecute> pExecute;
    

    然后每一行有赋值的都可以写成

    pExecute.reset(new CCircle);
    

    那你可以拨打Draw

    pExecute->Draw();
    

    【讨论】:

    • 谢谢,已经详细解释过了,现在可以正常使用了
    • 我不能投票,我没有足够的声望来投票..
    • 但我的答案对你有帮助,你应该接受其中一个
    猜你喜欢
    • 1970-01-01
    • 2017-04-28
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多