poncho
poncho

Reputation: 1150

pass derived class shared_ptr as parameter to function that wants base class shared_ptr

I've just through a massive refactoring of a project to add a base class in place of what is now a derived class of said base class (because I want more "types" of this class).

My problem is, some of the utility functions take a reference of the original class A as a shared_ptr and so a function declaration looks as follows:

void UtilityClass::func(shared_ptr<A> &a);

But now that I have the new base class B and A is derived from B (as well as a new class C which is derived from B) I'm getting a compile-time error when I try and pass an instance of A or C to the function whose declaration is now:

void UtilityClass::func(shared_ptr<B> &b);

If I try and pass:

shared_ptr<A> a;
utilclass.func(a);

I get a compile-time error saying that (paraphrase):

Cannot convert parameter 1 from 'std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty>'

But I'm not sure how else I'd solve this problem, func() adds the A, B or C instance to a std::vector of shared_ptr values.

Thanks for your time.

EDIT: I also have another function that takes a reference so that it can assign a new instance of B to it and then return it.

Upvotes: 2

Views: 7765

Answers (4)

user2626972
user2626972

Reputation: 589

This works:

class A {
public:
    virtual ~A() {};
    virtual void print() {
        puts("A prints");
    }
};
class B: public A {
public:
    void print() {
        puts("B prints");
    }
};


void func(std::shared_ptr<A> a) {
    a->print();
}


int main()
{
    std::shared_ptr<A> b_1(new B()); // can hold B*
    std::shared_ptr<B> b_2(new B());

    // both next function calls print "B prints"
    func(b_1);
    func(b_2); // can accept std::shared_ptr<B>
}

Upvotes: 0

Mike Seymour
Mike Seymour

Reputation: 254751

The problem is that you're passing by non-const reference, which means you need the argument type to match exactly.

Change the function to take the pointer by value or const reference; then implicit conversions (such as shared_ptr<Derived> to shared_ptr<Base>) can be applied to the argument.

Upvotes: 9

Jochen Kalmbach
Jochen Kalmbach

Reputation: 3684

The following works without any problems and is a supported scenario:

#include <tchar.h>
#include <memory> 
#include <iostream>

class Foo { };

class Bar : public Foo { };

int _tmain() 
{
  std::shared_ptr<Bar> b(new Bar());

  std::cout << b.use_count() <<std::endl;

  std::shared_ptr<Foo> f(b);

  std::cout << b.use_count() <<std::endl;
  std::cout << f.use_count() <<std::endl;

  return 0;
}

If the classes are derived, no problems should occur.

Upvotes: 2

doctorlove
doctorlove

Reputation: 19282

Change shared_ptr<A> a; to shared_ptr<B> a; You can still assign it a pointer of the more derived type, but achieve polymorphism via the base class.

Upvotes: 1

Related Questions