Downcasting a const std::list<const unique_ptr<Base>> - c++

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.

Related

Should functions return pointer to derived or base class?

When a function needs to return an object. Should it return it through a pointer to derived or base?
class B{
}
class D:public B{
}
// way 1: return pointer to derived
D* createDerived(){
D* d = new D();
return d;
}
// way 2: return pointer to base
B* createDerived(){
B* d = new D();
return d;
}
I have heard of "program to an interface not an implementation" which would suggest that we should return a pointer to base. However my intuition says it is better in this case to return a pointer to derived, because if the client code uses base pointers, this function would still work! On the other hand, if we return pointer to base and the client code uses derived pointers, this would not work for them. It seems that by returning a more "specific" pointer, we are allowing more flexibility for client code.
Another way to look at it is from the perspective of "program by contract." One of the suggestions is to promise as little as you can. By promising that we will return a very specific object, we follow this rule. However if we return a base pointer, it seems to me that we are promising a lot more.
Which is better design? Is my reasoning above correct?
I have a lot to learn on how to make modular, maintainable, extensible software, so please excuse if my reasoning/conclusion is nooby. I am very interested in learning. Thank you so much for your time.
It isn't possible to answer this question in a general way. In particular, returning the more derived object imposes additional restrictions on future implementations of the method, while returning the base class imposes more restrictions on the caller. Which is best depends on the design of the application or library, and in particular the scope of functionality offered by B and D and the overall design of the API.
In general, you want to return the most-derived, or, loosely speaking, the most functional class, which doesn't constrain your future implementation choices. This allows your clients to use the return value efficiently, while still allowing you to the change the implementation in the future.
The primary downside of using the derived class D is that you expose more details to the client, which may be difficult or impossible to reverse later.
For example, imagine that that you have a method reverse(std::ReversibleContainer &cont), which takes a container and returns a reversed snapshot of it (i.e., changes to the underlying container don't effect the returned snapshot).
In your initial implementation, you might decide to implement this as:
template<class BidirectionalIterator>
std::list<T> reverse(BidirectionalIterator &start, BidirectionalIterator &end) {
std::vector output;
std::copy(input.begin(), input.end(), back_inserter(output))
return output;
}
Later on, you might realize that you can avoid the copy of the underlying data for certain cases where the container (and elements) are constant, for example:
ImmutableIterator reverse(ImmutableBiderectionalIterator &input) {
return ReversingImmutableBiderectionalIterator(input);
}
This container can use the knowledge that the input container is read-only to return a view of the input container, avoiding the copy, which simply remaps each access to result in the same semantics as a reversed container.
I suggest you to rename member functions to createB and createD and in second case return pointer to derived class, because you always can cast derived class pointer to base class, when reverse cast may fail.
The correct answer imo is neither. There is usually no need to return raw pointers from functions in your own code (exceptions below).
Instead, just return the created object itself:
class B { virtual ~B(){} };
class D : public B {};
// this function would make real sense only if D were a class template
auto createD()
{
return D{};
}
This suffices in about any cases. Moreover, and importantly, it expresses what you get, namely an object of type D which you can use as required. Instead, when you get a raw pointer, it's from the first (i.e. without guessing the behaviour from the function name, reading the documentation, etc.) unclear what you're allowed to do with this raw pointer. Can you wrap it inside a unique_ptr? Are you allowed to delete it? Unclear. Returning an object (or better, a well-designed object, which basically means consistent RAII) releases you from having to answer those question -- just do what you want with the object.
Further, if you really need the pointer (which is an abstraction from the object), you can still wrap the return inside a suitable smart pointer like
auto d_uptr = std::make_unique<D>(createDerived());
auto d_sptr = std::make_shared<D>(createDerived());
or, similarly, also into smart base class pointers,
std::unique_ptr<B> = std::make_unique<D>(createDerived());
std::shared_ptr<B> b_sptr = std::make_shared<D>(createDerived());
This uses copy elision to construct the pointees and produces no overhead as compared to your function returning a D*. Note that as a rule the pointer should be a smart pointer, because only then you are freed directly from the obligation of having to delete it correctly somewhere later in the code.
One exception where you need raw pointers as function return types is the clone pattern, which applies when you want to copy an object via a base class pointer. Here one should use smart pointers as well as the function invoked by the user, but inside the class one has to use raw pointers in order to allow for covariant return types of virtual functions:
class B
{
virtual ~B(){}
auto clone() const
{
return std::unique_ptr<B>(clone_impl());
}
protected:
virtual B* clone_impl() const = 0;
};
class D : public B
{
protected:
virtual D* clone_impl() const { return new D{*this}; };
};
There might be a lot of other exceptions (e.g. always when covariance is used) which I don't have in mind at the moment. But those are not that important imo.
Summarizing: don't use raw pointers as function return types unless you have a good reason to do so.

C++ sorting container of base class pointers to derived objects

I have an std::list of base class pointers, all of which point to one of the two derived object classes. An instance of the base class is never declared, and, although the base class is not abstract, every member function is declared as virtual. Consider the code below:
class A
{
public:
A();
...
//member functions
...
protected:
int common_data_1;
std::string common_data_2;
...
};
class B: public A
{
public:
B();
//member functions
...
protected:
std::string class_B_specific_data;
...
};
class C: public A
{
public:
C();
//member functions
...
protected:
std::string class_C_specific_data;
...
};
These classes are instantiated as the appropriate base class via conditional statements and stored in an std::list by the base class pointer simultaneously in the same block of code like so:
std::list<A*> ptrList;
//conditional statements either create a B or C object
//and then that object is appended to the list
if (blahblah = true)
A* entry = new B();
else
A* entry = new C();
ptrList.append(entry);
I need to perform an insertion sort on this container of base class pointers based on an integer value that both derived classes inherit; however, in my previous attempts and upon inspection with a debugger tool, I find that my insertion sort algorithm properly makes the correct comparisons when accessing the integer that the comparison is based on, but I am unable to swap the position of the base class pointers in the std::list. I want to sort this container of pointers so that I can easily print the data in the proper order with a simple for loop.
This is clearly the result of a misunderstanding of pointer semantics, but to much avail I have been unable to find any reference or example that elucidates or solves the issue I am experiencing.
Any result that I have found either on this site or elsewhere solves this problem by using a container of the actual objects instead of a container of pointers to the objects. But, in my case, I can't do this because my code relies on the polymorphic behavior of the base class in order to have one big list of derived objects, instead of multiple lists for each derived object. Obviously, this makes calling member functions of the correct derived class extremely easy, and I would rather not redesign the entire structure of my data if I can avoid it.
If requested, I can post snippets of my code and/or the attempts that I have made to properly swap these pointer positions inside the container; however, I am unsure if this would even be helpful, since I am clearly using the wrong syntax to handle the pointers.
I appreciate any feedback; this problem has been plaguing me for the past few weeks and it is definitely time for me to step back and ask for assistance. I have a feeling that I am over-analyzing this issue, and that is most likely what is preventing me from solving the problem.
Assuming your goal is to sort an existing container, sort has a Compare comp argument that allows your to change its default behavior. To use it, you define a functor (a class that overrides operator()) that knows how you want your pointers to be compared. In this case, you want to define one that compares the common_data_1 that the pointed-to objects have.
class Comparator {
public:
bool operator(A* left, A* right) {
//You can do whatever logic you need here, here's an example:
return (a->common_data_1) < (b->common_data_2);
}
}
Then, call sort on your list:
ptrList.sort(Comparator());
I like #IanPudney's answer, though I typically use a lambda:
ptrList.sort([](A* first, A* second)
{return first->common_data_1 < second->common_data_1;}
);
Replace common_data_1 with whatever data member or function you want to use to sort.

In C++ objects: Should I be casting pointers with the parent class or should I be casting with the actual class itself

I have this parent class in C++
//ParentClass header file
public ParentClass{
public:
ParentClass();
virtual void someParentFunction();
private:
//other member variables and functions
};
//Functions implemented done in respective .cpp file
I extended this class so I have a child that looks like this
//ChildOneClass header file
public ChildOneClass : public ParentClass{
public:
//Constructors and other functions
private:
//Other members
};
//Functions implemented in respective .cpp file
Example declaration:
//Dynamically create one ChildOneClass object
ChildOneClass * c = new ChildOneClass();
//I know this is never done, but for example purposes i just did this
void * v = c;
I know if you have a pointer that points to the object you can do both:
((ParentClass *) v)->someParentFunction();
or:
((ChildOneClass *) v)->someParentFunction();
But which way is the correct way? Does it matter if I cast a pointer thats pointing to the subclass as a parent class? Sorry if this is confusing please give me some feedback if the question is confusing. I'll do my best to clarify
The only correct cast of a void* to a class pointer is the cast to the original class pointer type passed to the void*. Anything else may lead to unexpected results (eg.: having virtual or multiple inheritance)
NOTE: This answer addresses a later revision of the original question, which has since been reverted. For an answer to the original and current revision of the question, please see Dieter Lucking's answer.
If you want to call someParentFunction() on a class which may have a derived class which contains that function, you'll want to use dynamic_cast to the most base class with which that call is valid:
GrandParentClass *g = ...;
if (ParentClass* pc = dynamic_cast<ParentClass*>(g)) {
// ok, it's a ParentClass, this is safe
pc->someParentFunction();
}
else {
// not a ParentClass, do something else, log an error, throw, etc.
}
There's no reason to cast all the way down to ChildOneClass, since you would miss all the types that are ParentClass but are not ChildOneClass. This covers all the valid subsets. Note that GrandParentClass would need to be polymorphic in order for this to work (e.g. GrandParentClass has a virtual member function).
When you are creating polymorphic hierarchies you should be thinking in terms of interfaces. Ideally you should never need to cast. However in some cases it is necessary.
When you cast it should be to the specific interface that you need. So if you need to process objects of the derived type cast to the derived type. If you need to process objects of the base type cast to the base type.
Your design should make it obvious what interface is being dealt with at which point in the system.
If you are casting a lot (or even at all) it could be a symptom of poor design.

Passing shared_ptr<Derived> as shared_ptr<Base>

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

Returning abstract datatypes in C++ without dangling pointers

Hallo,
I come from a C# background and don't have a lot of C++ experience. To produce clean code I try to separate implementation and interfaces and use inheritance when possible. And when I tried to apply typical C# concepts to C++ I ran into a problem that I've been unable to resolve so far. I assume that this is probably trivial for an experienced C++ programmer but it has been driving me crazy for quite a while.
First I declare a base class (it contains no logic at the moment but it will in the future)
class PropertyBase : public IProperty
{
};
Then I define an interface for the Properties
class IProperty
{
public:
virtual ~IProperty() {};
virtual PropertyBase correct(const ICorrector &corrector) = 0;
virtual PropertyBase joinWith(const PropertyBase &partner, const IRecombinator &recombinator) = 0;
};
This is where the problem comes in: The compiler returns errors for the two virtual functions saying that it is not allowed to declare a function that returns an abstract class. Of course I don't want to return an object of the type PropertyBase. I want to declare other classes that inherit from PropertyBase that return an instance of themselves.
Now I've read that a possible way around it is to modify IProperty like this to return pointers:
class IProperty
{
public:
virtual ~IProperty() {};
virtual PropertyBase* correct(const ICorrector &corrector) = 0;
virtual PropertyBase* joinWith(const PropertyBase &partner, const IRecombinator &recombinator) = 0;
};
However I would like to avoid this if possible to prevent memory leaks. It would be great if someone would have a better idea to deal with this problem.
Thank you very much
If you're afraid of memory leaks, switch to smart pointers. That has the additional benefit of being self-documenting wrt. ownership of the returned object.
class IProperty
{
public:
virtual ~IProperty() {};
virtual std::unique_ptr<PropertyBase> correct(const ICorrector &) = 0;
virtual std::unique_ptr<PropertyBase> joinWith(const PropertyBase &,
const IRecombinator &) = 0;
};
In your client code:
std::unique_ptr<PropertyBase> pb(property.correct(corrector));
// use pb and forget about it; smart pointers do their own cleanup
Or, if you want reference counting on the object:
std::shared_ptr<PropertyBase> pb(property.correct(corrector));
See MSDN docs for unique_ptr, shared_ptr.
This may not be the answer you're looking for, but it seems to me that you are a little confused about pointers and values in C++.
You have to return either a pointer, or a reference, in C++ if you want proper ad-hoc polymorphism. In this case, the compiler issued an error, because the base class was abstract. If instantiating an abstract class would be possible, it would have "holes" in it.
The thumb rule is: Whenever you have a class hierarchy, never return objects of such types by value. Suppose you have class Base { int x; }, and class Derived : public Base { int y; }. If you do this:
Base Function() { Derived d; return d; }
...
Base b = Function();
Then b will not be a value of class Derived "hiding behind" a Base. The value b WILL be Base. The compiler will "slice off" the differences between Derived and Base, and put it into b.
In C++, you will have to use pointers or references to facilitate ad-hoc polymorphism. References in C# is pretty much the same thing as pointers in C++, with the exception that you do not have to free the objects in C#, as the garbage collector will handle this for you.
There's nothing wrong with returning a pointer to an object. If you're worried about memory leaks, as you should be, the solution is to use smart pointers to store the returned pointer. The most flexible of these is shared_ptr from boost or the upcoming C++0x standard.
More generally, if you're going to be doing any serious amount of work in C++, getting comfortable with pointers and memory management is kind of essential. For in-depth coverage of that and other tricky aspects of C++, I strongly recommend the Effective C++ books by Scott Meyers and the Exceptional C++ books by Herb Sutter.
There is very easy solution to this problem. Use pointers or references for return values, but instead of returning ownership in the pointers, you should not return ownership.
For example:
class A : public Base
{
public:
Base *correct(const I &c)
{ p2 = do_something(c); return &p2; }
...
private:
A2 p2;
};
What makes this work is that you store the p2 inside the class and never pass ownership of the objects to outside of it. The function in the interface will not create new objects, but instead it'll just return existing one, configured to correct state based on function's parameters. This is a good alternative to the unique_ptr and shared_ptr solution which relies on heap allocation and creating new objects and passing them around.
Now the nice trick with this is that you need to list all possible types you want to return from your correct() function in the data members of the class. For example, if sometimes you would return different type, it'd look like this:
class B : public Base
{
public:
Base *correct(const I &c) {
switch(c.get_bool()) {
case false: p3 = do_something_else(c); return &p3;
case true: p4 = do_something(c); return &p4;
};
}
private:
B3 p3;
B4 p4;
};
But placing your objects p3 and p4 inside the current B object will solve this problem completely.