std::shared_ptr of abstract class to instantiate derived class

15,730

Solution 1

That's easy. Look at code and feel.

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();

Solution 2

The method std::make_shared<T> creates a shared pointer object of type T and calls its constructor. So instead of calling new call 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 is also able to use paramaters, which are forwarded to the constructor, assuming there is a construcotr with that paramater list.

Solution 3

The line

IExecute *ppCIExecuteExecuteOperation = NULL;

should be replace with

std::shared_ptr<IExecute> pExecute;

and then each of the lines with assignments can be written as

pExecute.reset(new CCircle);

Then you can call Draw

pExecute->Draw();
Share:
15,730
Barry
Author by

Barry

Updated on June 04, 2022

Comments

  • Barry
    Barry almost 2 years

    I am trying to use std::shared_ptr, but i am not sure if i can use shared_ptr for a abstract class and call a derived class from this smart pointer. Here is the code that i have at present

    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();
    

    Here IExecute is a abstract class and CCircle, CSquare, CRhombus is a derived class of IExecute.

    All I want to do is use shared_ptr<IEXectue>pCIExecuteExecuteOperation(nullptr) and inside a switch statement make it point to one of the derived class, How can i achieve this?

    Edit: The answers were to use make_shared or reset()

    Thanks guys, I dint expect it to be so easy.

  • evotion
    evotion over 9 years
    Isn't it safer in terms of memory leaks to use std::make_shared instead of new?
  • ikh
    ikh over 9 years
    @evotion why? could you explain me?
  • evotion
    evotion over 9 years
    The notes at cppreference show this. Well the question is, if this code is even good practice, because it is hard to read without make_shared, but it can lead to problems.
  • ikh
    ikh over 9 years
    @evotion No, that's okay to directly new in this case. The point of that cppref page is relate to order of evalution, but in my case that doesn't occur.
  • Barry
    Barry over 9 years
    Thank you guys, but i want to know what is the difference in using std::make_shared and "new" as mentioned in the above code
  • evotion
    evotion over 9 years
    In this case not because you are using reset instead of constructing a new shared_ptr by calling the std::shared constructor. I never seen that use of reset(). Is there any reason preferring reset()? In my opinion a call to make_shared or the ctor of shared_ptr combined with the assignment operator is better to read.
  • evotion
    evotion over 9 years
    @user2882262 I prefer the make_shared approach because it improves the readability. It also seams to me that it is the most used approach, despite maybe the shared_ptr<T>(newT()) approach, which can lead to a memory leak as mentioned in an earlier post. I actually read some books and articles about shared_ptr, but it is the first time I see the use of reset for assigning a shared_ptr. If I am honest, I did not new of reset before and looked it up.
  • evotion
    evotion over 9 years
    Both approaches are referenced on cppreference and cplusplus as a method to acquire ownerwhip of an object, so its probably just a preference thing.
  • Barry
    Barry over 9 years
    Thank you @evotion for the detailed description..
  • Barry
    Barry over 9 years
    Thank you, it was explained in detail and its working now
  • Wojtek Surowka
    Wojtek Surowka over 9 years
  • Barry
    Barry over 9 years
    I can't vote up, I do not have enough reputation to vote..
  • Wojtek Surowka
    Wojtek Surowka over 9 years
    But I the answers helped you, you should accept one of them
  • ikh
    ikh over 9 years
    @evotion I use reset because it just makes code more shorter and easy.