Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement polymorphism with std::shared_ptr?

Tags:

I have seen some of the other questions on this topic, but have still not found the answer - I guess I'm missing something:

I defined two simple test classes:

class TestBase {    public:      TestBase ( ) { };     ~ TestBase ( ) { };    protected:      inline virtual int getInt ( )     {         return 0;     }  };  class TestDerived : public TestBase {    protected:      inline int getInt ( ) override     {         return 1;     }  }; 

I declared typedefs to simplify their usage with std::shared_ptr:

typedef std::shared_ptr<TestBase> spBase; typedef std::shared_ptr<TestDerived> spDerived; 

Problem: I cannot compile code to use these shared_ptr declarations polymorphically, even though base in all these cases is actually an instance of spDerived:

spBase base; spDerived derived = static_cast < spDerived > ( base ); 

error: no matching function for call to ‘std::shared_ptr::shared_ptr(spBase&)

spDerived derived = dynamic_cast < spDerived > ( base ); 

error: cannot dynamic_cast ‘base’ (of type ‘spBase {aka class std::shared_ptr}’) to type ‘spDerived {aka class std::shared_ptr}’ (target is not pointer or reference)

spDerived derived = static_pointer_cast < spDerived > ( base ); 

error: conversion from ‘std::shared_ptr >’ to non-scalar type ‘spDerived {aka std::shared_ptr}’ requested

spDerived derived = dynamic_pointer_cast < spDerived > ( base ); 

error: conversion from ‘std::shared_ptr >’ to non-scalar type ‘spDerived {aka std::shared_ptr}’ requested

I'm using C++11 on an Ubuntu 14.04 box with the default GCC tool chain. Compiler is gcc-4.9. What am I doing wrong? Can't a shared_pointer be used polymorphically?

like image 519
Vector Avatar asked Dec 16 '14 10:12

Vector


People also ask

How is shared_ptr implemented C++?

shared_ptr is a reference-counted smart pointer i.e. it can share ownership of a dynamically allocated object with other shared_ptr instances. To put it in another way, several shared_ptr objects can own (point to) the same memory(object) on the heap.

What does shared_ptr get () do?

A shared_ptr may share ownership of an object while storing a pointer to another object. get() returns the stored pointer, not the managed pointer.

When should you use shared_ptr?

So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object. When to use shared_ptr? Use shared_ptr if you want to share ownership of a resource.

Why would you choose shared_ptr instead of Unique_ptr?

Use unique_ptr when if you want to have single ownership(Exclusive) of resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. Use shared_ptr if you want to share ownership of resource .


1 Answers

A type passed in to std::static_pointer_cast and std::dynamic_pointer_cast as the first type template argument is the type of the converted pointer's type itself, not of the smart pointer type:

static_pointer_cast<T>(arg);                 .~~~^                   v  template <class T, class U>             .~~~~^              v  shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r);   dynamic_pointer_cast<T>(arg);                 .~~~~^                   v  template <class T, class U>             .~~~~^              v  shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r); 

With that said, you could call it like below:

spBase base = std::make_shared<TestDerived>(); spDerived derived = std::dynamic_pointer_cast<spDerived::element_type>(base); // or: spDerived derived2 = std::dynamic_pointer_cast<TestDerived>(base); 
like image 123
Piotr Skotnicki Avatar answered Sep 24 '22 15:09

Piotr Skotnicki