Passing shared_ptr<Derived> as shared_ptr<Base> - c++

What is the best method to go about passing a shared_ptr of a derived type to a function that takes a shared_ptr of a base type?
I generally pass shared_ptrs by reference to avoid a needless copy:
int foo(const shared_ptr<bar>& ptr);
but this doesn't work if I try to do something like
int foo(const shared_ptr<Base>& ptr);
...
shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);
I could use
foo(dynamic_pointer_cast<Base, Derived>(bar));
but this seems sub-optimal for two reasons:
A dynamic_cast seems a bit excessive for a simple derived-to-base cast.
As I understand it, dynamic_pointer_cast creates a copy (albeit a temporary one) of the pointer to pass to the function.
Is there a better solution?
Update for posterity:
It turned out to be an issue of a missing header file. Also, what I was trying to do here is considered an antipattern. Generally,
Functions that don't impact an object's lifetime (i.e. the object remains valid for the duration of the function) should take a plain reference or pointer, e.g. int foo(bar& b).
Functions that consume an object (i.e. are the final users of a given object) should take a unique_ptr by value, e.g. int foo(unique_ptr<bar> b). Callers should std::move the value into the function.
Functions that extend the lifetime of an object should take a shared_ptr by value, e.g. int foo(shared_ptr<bar> b). The usual advice to avoid circular references applies.
See Herb Sutter's Back to Basics talk for details.

This will also happen if you've forgotten to specify public inheritance on the derived class, i.e. if like me you write this:
class Derived : Base
{
};
Instead of:
class Derived : public Base
{
};

Although Base and Derived are covariant and raw pointers to them will act accordingly, shared_ptr<Base> and shared_ptr<Derived> are not covariant. The dynamic_pointer_cast is the correct and simplest way to handle this problem.
(Edit: static_pointer_cast would be more appropriate because you're casting from derived to base, which is safe and doesn't require runtime checks. See comments below.)
However, if your foo() function doesn't wish to take part in extending the lifetime (or, rather, take part in the shared ownership of the object), then its best to accept a const Base& and dereference the shared_ptr when passing it to foo().
void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);
As an aside, because shared_ptr types cannot be covariant, the rules of implicit conversions across covariant return types does not apply when returning types of shared_ptr<T>.

Also check that the #include of the header file containing the full declaration of the derived class is in your source file.
I had this problem. The std::shared<derived> would not cast to std::shared<base>. I had forward declared both classes so that I could hold pointers to them, but because I didn't have the #include the compiler could not see that one class was derived from the other.

Sounds like you're trying too hard. shared_ptr is cheap to copy; that's one of its goals. Passing them around by reference doesn't really accomplish much. If you don't want sharing, pass the raw pointer.
That said, there are two ways to do this that I can think of off the top of my head:
foo(shared_ptr<Base>(bar));
foo(static_pointer_cast<Base>(bar));

Related

Overloading function based on pointer type of unique_ptr parameter

I was under the impression that unique_ptr could infer class hierarchy in the same way that a normal pointer can, but when I try to overload a function like this:
void func(unique_ptr<Derived1>& d1);
void func(unique_ptr<Derived2>& d2);
And then call one of the functions like this:
unique_ptr<Base> b = make_unique<Derived1>();
func(b);
I get an error saying that no instance of overloaded function "func" matches the argument list. The runtime type of b is Derived1, so I expected that the first overload would be called.
Also, when I return a unique_ptr from a function, the compiler is able to cast (? not sure of the appropriate terminology) a derived class to a base class, so that something like this works:
unique_ptr<Base> create(){
return make_unique<Derived1>();
}
Often in my code I have variables declared as the result of functions like this. They're declared as base but have derived runtime types, and I would like to pass them into one single overloaded function.
How do I overload functions in the same way that I would with regular pointers where class hierarchies are involved?
You are right that the implicit conversion operations of all standard smart pointers model those of raw pointers. This allows the second snippet to compile, i.e.
unique_ptr<Base> create(){
return make_unique<Derived1>();
}
However, there is a misconception about the first snippet, as there is never a builtin implicit downcast-like conversion from base class to derived class. Using normal pointers,
void func(Derived1* d1);
void func(Derived2* d2);
Base* b = new Derived1();
func(b);
won't compile either. This makes sense in a the fundamental OOP sense - look at objects in an inheritance hierarchy through the base class interface, and hide the actual concrete runtime type.
If you need a design with that kind of dispatch, you want to read about the "Visitor" design pattern, which implements a technique called double (or multiple) dispatch. But the amount of boilerplate necessary to realize that gives you a hint why the language doesn't provide this kind of dispatch as a builtin.

Downcasting a const std::list<const unique_ptr<Base>>

I'm writing a modular software, and I'm heading some problem with interfaces and memory.
I've a Base class with some heavy work with association and composition so I prefer to write it once in an interface. Problem is to avoid any memory leak or problems only my base class should be able to see the fields. Nobody else than Base should modify mFields list or free the pointers it contains.
The problem is BaseField will be derived, and methods will be added and my program who will use the Derived method should directly get list of DerivedField:
class BaseField {} ;
class DerivedField : public BaseField {} ;
class Base {
protected:
unique_ptr<BaseField> & addField(unique_ptr<BaseField> f) ;
const unique_ptr<BaseField> & something() ;
const unique_ptr<BaseField> & something2() ;
const std::list<const unique_ptr<BaseField>> & getFields() ;
private:
std::list<const unique_ptr<BaseField>> mFields ;
}
class Derived : public Base {
public:
unique_ptr<DerivedField> & addField(params) ;
const unique_ptr<DerivedField> & something() ;
const unique_ptr<DerivedField> & something2() ;
const std::list<const unique_ptr<DerivedField>> & getFields() ;
}
So my question is how to get
const std::list<const unique_ptr<DerivedField>> & in Derived::getFields() with Base::getFields() ?
EDIT:
I think I didn't explain my problem clearly. I understand what #NicolBolas is saying and I agreee with him but doesn't really help me so let's present it that way:
My software should solve different problems types such as Problem1 Problem2 and Problem3
The fact is all of thoses problem have exactly same subproblems structure such as SubProblem1 SubProblem2 SubProblem3
So to avoid code repetition I decide to write a BaseProblem class and a BaseSubProblems who will repesent the structure and the comon operations for every Problem (such as addSubProblem(BaseSubProblem *)).
Base problem is not instanciable because protected constructor (it's only a structure provided to avoid code repetition). Also the addSubProblem(SubProblem *) method is protected so only derived Problem can add SubProblem
Because of that every user who creates a Problem1 know that all of the SubProblem contained in Problem1 are type of SubProblem1.
So actually I use std::list<SubProblem *> in BaseProblem and my derived Problem class gives access with std::list<SubProblem1 *> Problems1::getSubProblems()
I would like to be able to declare that only BaseProblem owns the SubProbblems even if only the derived Problems know the real type of SubProblems
I hope this explanation is better than the previous one.
You can't do that. In fact, you can't implement any of your Derived interface like that. C++ doesn't work that way.
The types unique_ptr<Derived> and unique_ptr<Base> are completely unrelated types, as far as C++ is concerend. You cannot cast or convert a value, pointer, or reference of one type to the other. Well, you can with pointers/references, but you will get undefined behavior. The same goes for std::list<T>.
Your problem is that you seem to want to pass references to a unique_ptr around. This is a poor API. If someone takes a unique_ptr, then that should mean that they are claiming ownership of that object. By passing a unique_ptr to addField, the caller is telling Base to take ownership of that pointer. For it to return a reference to that pointer is a violation of the unique ownership idea of a unique_ptr.
addField and its ilk should just return naked pointers: Base* and such. With naked pointers, there are no ownership implications.
As for getFields... well, you're going to have to come up with an API based on naked pointers for exposing such a list. Maybe you should internally have a vector<Base*> that you can expose, or you could create an iterator wrapper around list's iterators that extract the pointer from the unique_ptr.
It should also be noted that this faux-overriding syntax you're using, where the derived class hides base class member functions with versions that use its own pointers, is generally poor OOP style. It requires way too much "downcasting", which is dangerous and il-advised. There's nothing stopping a user from sending something that isn't a Derived into addFields in the base class, and users of the class should not themselves care one way or the other.
And if they have to care, then you're doing OOP wrong.

What does this mean in Virtual Functions?

Late binding occurs only with virtual functions, and only when you’re using an address of the base class where those virtual functions exist.
This is an extract from a famous text book.
My question is...what exactly does the author mean by 'using an address' ?
Background
The relevant scenarios are when you have a pointer or reference with a static type of pointer-to-Base or reference-to-Base, regardless of whether the pointer or reference is a local variable, a function parameter, member variable etc..
// accessed via pointer...
Base* p = new Derived(); p->fn(); // (ref.1)
void f(Base* p) { p->fn(); } Derived d; f(&d);
// accessed via reference...
const Base& r = static_derived;
void f(Base& b) { b.fn(); } Derived d; f(d);
Late binding occurs only with virtual functions, and only when you’re using an address of the base class where those virtual functions exist.
The statement is misleading in two ways:
Late binding may occur under the specified circumstances, but the optimiser's allowed to bind at compile or link time instead if it can work out the dynamic type involved. For example, if both lines of code in (ref.1) above appeared together in a function body, the compiler can discern that p addresses a Derived object and hardcode a call straight to any Derived::fn() override, or failing that the Base-class implementation.
The situations above involved pointers and references. As far as the C++ Standard's concerned, the mechanisms used to implement references are left unspecified and we humble programmers shouldn't assume they're effectively pointers with different notations for use, so we shouldn't consider them to store the "address" of the variable they reference, but thinking of them as glorified pointers storing addresses is generally practical and the quoted statement's lumped them in with pointers as mechanisms "using an address".
I guess that the emphasis is not on using an address, which would be wrong since a reference would do as well. Rather, the point is that the static type of the address or reference is that of a "base class where those virtual functions exist". This is not always the case when you have multiple baseclasses or when the baseclass hase a baseclass itself where the memberfunction in question does not exist.

Usefulness of covariant return types in C++ clone idiom?

The usual clone idiom makes use of covariant return types:
struct Base {
virtual Base* clone();
};
struct Derived : public Base {
Derived* clone();
};
I've read things to the effect that covariant return types were a later addition to C++, and older compilers may not support them. In this case the Derived class must declare its clone member function to return a Base*. Since, presumably, I'm only accessing Derived objects through Base pointers and/or references when using this idiom, what is the real use/benefit to declaring the return type Derived*?
Also, a related question:
I would prefer to use smart pointers to express transfer-of-ownership semantics for the clone signature. This is not possible when using covariant return types, as auto_ptr<Derived> is not covariant with auto_ptr<Base>. (Please note that I'm not looking for a lecture on the use of smart pointers -- auto_ptr is just used as an example here). So in this case, is there any reason not to have Derived return auto_ptr<Base>? Is there a better way to express the transfer-of-ownership semantics?
Since, presumably, I'm only accessing Derived objects through Base pointers and/or references when using this idiom...
You presume wrong. Just because a Base class exists doesn't mean you'll always be using it. If I have a Shape class with sub classes Circle and Rectangle, and I also have a Window class. I'm not going to use a Shape* for a the window's position and size when I can just use Rectangle.
For the transfer-of-ownership, you shouldn't be using smart pointers anyway. I know you don't want a lecture, but I'm not saying that smart pointers are bad, you just shouldn't be using them in clone(). You can't transfer ownership of something that has no ownership in the first place. If someone wants an auto_ptr then they should construct it with the cloned raw pointer. Same goes for other smart pointer types.
It's useful when you have a pointer to Derived and want to get a clone of it:
Derived *ptr = ...;
Derived *clone = ptr->clone();
without covariant return types you must do an explicit cast:
Derived *clone2 = (Derived*)ptr->clone();
Note that Derived may be a base class for even more derived classes, in that case it makes even more sense.
Unfortunately auto_ptr<Derived> and auto_ptr<Base> are not covariant. So you must return the same type from all clone functions in that case.

Overloading based on specialization in C++

I'm trying to create a function which is overloaded based on the specialization of its parameter, such as this:
class DrawableObject...;
class Mobile : public DrawableObject...;
class Game
{
AddObject(DrawableObject * object)
{
// do something with object
}
AddObject(Mobile * object)
{
AddObject(dynamic_cast<DrawableObject *>(object));
DoSomethingSpecificForSpecializedClass();
}
};
...but my MS compiler is giving me this error:
error C2681: 'Mobile *' : invalid expression type for dynamic_cast
Both classes have virtual functions. Is this the wrong cast for up-casting in this situation? I have tried with a C-style cast and everything functions as intended. Also, are there any potential pit-falls with this design?
For explicit upcasting, use static_cast.
Your design should work fine. Be aware that calls to AddObject() will be ambiguous if you try to pass an object that can be implicitly converted to both Mobile* and DrawableObject*, such as a pointer to a class derived from Mobile.
As Neil stated, the cast is simply wrong. dynamic_cast<> is for downcasting from base towards derived not the other way around. A better approach is to factor out the common code like:
class Game {
protected:
void commonAddObject(DrawableObject *obj) {
// do common stuff here
}
public:
void addObject(DrawableObject *obj) {
commonAddObject(obj);
// do DrawableObject specific stuff here
}
void addObject(MobileObject *obj) {
commonAddObject(obj);
// do MobileObject specific stuff here
}
};
or to create separate methods for DrawableObject and MobileObject that do not rely on overloading by types. I prefer to steer clear of casting altogether if I can.
The cast is wrong, and completely unecessary - Mobile already is a DrawableObject.
Upcasting is always free and safe. That means you don't need to use a protected dynamic_cast. A static_cast would be the proper way to do this, although a c-style cast will work as well. In reality you should be able to do away with the second AddObject function because if you passed a pointer to a Mobile object into the DrawableObject function it would call the proper function without needing any casting. Unless you are planning on putting specialized functionality in the overloaded function I wouldn't write it.
...or remove your AddObject(Mobile * object) overload entirely. Without that function there, it will be "implicitly casted" to it's base class, and the AddObject(DrawableObject*) function would have been called. There is no need for you to manually add an overload and a cast for each type in your hierarchy.
Edit Code was added, I want to clarify some suggestions about your design.
Either your "Game" class treats all objects uniformly, or it does not. If it does not, there is no point in providing a generic "AddObject" overload that is publicly available - you're already coupled tightly to the individual objects, so you might as well drop it and the charade of a loosely coupled design.. You could still have it as a private helper function, AddObjectInternal. Since it's not an overload, you won't need the cast to disambiguate the call.
If you are or hope to treat all objects uniformly, consider putting such logic that you're currently putting in the AddObject overloads into virtual functions on the object class. Then, you only have one AddObject method, which calls the virtual functions on the object added.