data inheritance in C++ - c++

I have two class, one for storing base data, and the other for storing additional data as following:
struct AnimationState(){
virtual ~ AnimationState(){};
Vector3f m_spacialData;
float m_fTimeStamp;
}
And the derived class:
struct HermiteAnimationState() : public AnimationState{
virtual ~HermiteAnimationState(){};
Vector3f m_tangentIn;
Vector3f m_tangentOut;
}
My question: is how can I, at first, create an instance of HermiteAnimationState, and then upcast it to AnimationState for storing in a vector like this:
std::vector<AnimationState> m_vStates;
...
Lately, I can get the object AnimationState and downcast it to HermiteAnimationState for accessing the additional data (member m_tangentIn and m_tangentOut).
HermiteAnimationState* p = dynamic_cast<HermiteAnimationState*>(&m_vStates[i])

The way polymorphism works in C++ is that if B is a base class and D is derived from B, then:
a pointer to D can be used where a pointer to B is expected
a reference to D can be used where a reference to B is expected
What you can't do in C++ is actually use a value of type D in a context where a value of type B is expected. For example, you can't store derived objects in an array of base object. This makes sense when you consider that a derived object may have a different size from a base object.
Similarly, you can't store derived objects in a vector of base objects.
What you can do is store pointers to HermiteAnimationState in a vector of pointers to AnimationState. It's up to you how to manage the memory. For example, the following would be valid:
std::vector<AnimationState*> m_vStates;
HermiteAnimationState h_a_s;
m_vStates.push_back(&h_a_s);
...
HermiteAnimationState* p = dynamic_cast<HermiteAnimationState*>(m_vStates[i])
Since h_a_s is a local variable, it'll be destroyed automatically at the end of its scope.
But this is probably an unworkable approach, because you probably want the objects referred to by the vector elements to persist beyond the current scope. We can use std::unique_ptr for this purpose. A std::unique_ptr owns the object it points to, and as long as it stays alive, so does that object; and it deletes the object when it is itself destroyed. So a vector of std::unique_ptr objects behaves like a vector of objects themselves in terms of memory management. Now you can do
std::vector<std::unique_ptr<AnimationState*>> m_vStates;
m_vStates.emplace_back(new HermiteAnimationState);
...
HermiteAnimationState* p =
dynamic_cast<HermiteAnimationState*>(m_vStates[i].get());
(Note, however, that you can't copy this vector; you can only move it.)

Basically, you need to use some kind of reference to the pointed object because you need dynamic polymorphism.
The simplest but error-prone would be using "naked" pointers. The first thing that is problematic with this is that you have to do the destroying manually: containers will destroy the pointer, not what is pointed.
The safer way to do this is to use smart pointers, which are designed to do the destruction depending on a pre-fixed rule that the smart pointer embedd in it's type. The simplest one and certainly the best choice if you are doubting is std::unique_ptr, which can't be copied but can be moved. The other choice, which should be thought carefully about before being used, is the std::shared_ptr which is useful IFF you don't know when you should destroy these objects but you know it's when some systems will refer no more to it. Some other systems might just be observing that object, in which case std::weak_ptr.
Now, from reading your question, I think you are certainly processing a lot of these animation data. There is an obvious design issue there, I think, I might be wrong.
However, it looks like, if you have a lot of these AnimationState to manage, in a loop, you will get performance issues. This is common issues in games, mainly caused by "cache conherency".
What I would recommand in this case, would be to NOT use
inheritance: it's an invitation to the cpu to jump all over the place and trigger cache misses;
dynamic_cast: it's one of the few operations that are not guaranteed to end in a predictable time (with new and delete for example), which basically mean that if you are in a critical loop, you can lose a lot of time through it. In some cases, you can't avoid using dynamic cast (like when doing dynamic plugins), but in most cases, using it just because you have chosen to use inheritance is just wrong. If you use inheritance, then you should use virtual calls.
However, what I suggest is even more drastic: don't use inheritance at all.
Obviously, this is only an advice. If you are not doing something with a critical loop, it doesn't matter. I'm just worried because it looks like you are doing some inheritance for composition, which always have bad consequences both on readability of the code and performance.

Related

C++ several instances (but not all) of a class sharing a vector

I want to have a class C, such that instances of C hold a std::vector<int> as a private member. Now many instances (but not all) of C will share that vector and keeping a copy for each instance is what I would want to avoid.
If this vector were a single integer for example, I could create a template class for C and have it like this:
template <int N>
class C {
// something
};
If instead of some instances I wanted all instances to share that vector then I would declare the variable static as
class C {
static std::vector<int> _vec;
What I am looking is for something intermediate. I could for example keep a shared_ptr as a private non-static member as in
class C {
std::shared_ptr<std::vector<int>> _vec;
}
And that would take care of the lifetime of the object, with some overhead for maintaining shared ownership and also an extra pointer per-instance. I could keep a reference instead and let the creator of the instances take care of the lifetime, but avoid the overhead of the shared_ptr. Is there a better approach to this design question?
…such that instances of C hold a std::vector as a private member. Now many instances (but not all) of C will share that vector
So, that's self-contradicting. You can't hold an instance and share the instance safely.
This is a classical use case of pointers; even more specifically, classical use case of a shared pointer, as you already noticed.
I could keep a reference instead and let the creator of the instances take care of the lifetime,
/me sounds the access-after-destruction alarm You're about to find out that won't work. The lifetime is not like you think, but ends when the owning object's lifetime ends. So, this breaks. (Also, you'll find that under the hood, handing out references compiles down to the same code as handing out raw pointers – it's just safer and does the dereferencing automagically within the language; you're not actually saving a memory indirection there. The classes containing the reference still need to know the address of the object they're handling, and that's the same as having a pointer, if you ask your CPU.)
It breaks, unless the thing handing out the references keeps a count on how many references it handed out, subtracts many references it handed out belong to C instances that were deconstructed, and then deconstructs the vector as soon as that number reaches 0. Take a wild guess what a shared_ptr does! Exactly this reference counting.
Often, however, the access logic is easier; for example,
I have a vector of C, std::vector<C> lexicon, and all held C._vec need to get removed exactly when that full lexicon goes out of scope, so I handle that manually
actually doesn't need reference counting and hence is lower-overhead. You can indeed solve that by handing out references – but I'd actually prefer to hand out raw pointers in that case: they just as much don't imply ownership, and you don't accidentally make a copy of the std::vector<int> when you pass the pointer by value.
If your lifetime tracking isn't as easy as that example :
There's no magic usage tracking in references; and you need something to keep track of whether something is still holding some handle to your individual vector. That tracking is exactly the "overhead" shared_ptr incurs. No way around it.
A private shared_ptr is hence the right approach:
class C {
private:
std::shared_ptr<std::vector<int>> _vec;
}
Your static approach takes you nowhere here - it only makes sense if all, and really all, instances share the same vector which should essentially live from the beginning of time till the end, and even then, it's a bit of a solution that can lead to additional headaches in form of the static initialization order fiasco. I'd advise to not do that under almost all circumstances.
(Plus, a static member also just boils down to the code looking up the same address – so, performance-wise, same as a pointer. Again, nothing really won here.)

Correctly using smart pointers

I'm having trouble getting things organized properly with smart pointers. Almost to the point that I feel compelled to go back to using normal pointers.
I would like to make it easy to use smart pointers throughout the program without having to type shared_ptr<...> every time. One solution I think of right away is to make a template class and add a typedef sptr to it so I can do class Derived : public Object < Derived > .. and then use Derived::sptr = ... But this obviously is horrible because it does not work with another class that is then derived from Derived object.
And even doing typedef shared_ptr<..> MyObjectPtr is horrible because then it needs to be done for each kind of smart pointer for consistency's sake, or at least for unique_ptr and shared_ptr.
So what's the standard way people use smart pointers? Because frankly I'm starting to see it as being too much hassle to use them. :/
So what's the standard way people use smart pointers?
Rarely. The fact that you find it a hassle to use them is a sign that you over-use pointers. Try to refactor your code to make pointers the exception, not the rule. shared_ptr in particular has its niche, but it’s a small one: namely, when you genuinely have to share ownership of a resource between several objects. This is a rare situation.
Because frankly I'm starting to see it as being too much hassle to use them. :/
Agreed. That’s the main reason not to use pointers.
There are more ways to avoid pointers. In particular, shared_ptr really only needs to spelled out when you actually need to pass ownership. In functions which don’t deal with ownership, you wouldn’t pass a shared_ptr, or a raw pointer; you would pass a reference, and dereference the pointer upon calling the function.
And inside functions you almost never need to spell out the type; for instance, you can (and should) simply say auto x = …; instead of shared_ptr<Class> x = …; to initialise variables.
In summary, you should only need to spell out shared_ptr in very few places in your code.
I have a lot of code that creates objects dynamically. So using pointers is necessary because the number of objects is not known from the start. An object is created in one subsystem, then stored in another, then passed for further processing to the subsystem that created it. So that I guess means using shared_ptr. Good design? I don't know, but it seems most logical to ask subsystem to create a concrete object that it owns, return a pointer to an interface for that object and then pass it for further processing to another piece of code that will interact with the object through it's abstract interface.
I could return unique_ptr from factory method. But then I would run into trouble if I need to pass the object for processing multiple times. Because I would still need to know about the object after I pass it to another method and unique_ptr would mean that I lose track of the object after doing move(). Since I need to have at least two references to the object this means using shared_ptr.
I heard somewhere that most commonly used smart pointer is unique_ptr. Certainly not so in my application. I end up with using shared_ptr mush more often. Is this a sign of bad design then?

Is it alright to return a reference to a non-pointer member variable as a pointer?

I recently came across some C++ code that looked like this:
class SomeObject
{
private:
// NOT a pointer
BigObject foobar;
public:
BigObject * getFoobar() const
{
return &foobar;
}
};
I asked the programmer why he didn't just make foobar a pointer, and he said that this way he didn't have to worry about allocating/deallocating memory. I asked if he considered using some smart pointer, he said this worked just as well.
Is this bad practice? It seems very hackish.
That's perfectly reasonable, and not "hackish" in any way; although it might be considered better to return a reference to indicate that the object definitely exists. A pointer might be null, and might lead some to think that they should delete it after use.
The object has to exist somewhere, and existing as a member of an object is usually as good as existing anywhere else. Adding an extra level of indirection by dynamically allocating it separately from the object that owns it makes the code less efficient, and adds the burden of making sure it's correctly deallocated.
Of course, the member function can't be const if it returns a non-const reference or pointer to a member. That's another advantage of making it a member: a const qualifier on SomeObject applies to its members too, but doesn't apply to any objects it merely has a pointer to.
The only danger is that the object might be destroyed while someone still has a pointer or reference to it; but that danger is still present however you manage it. Smart pointers can help here, if the object lifetimes are too complex to manage otherwise.
You are returning a pointer to a member variable not a reference. This is bad design.
Your class manages the lifetime of foobar object and by returning a pointer to its members you enable the consumers of your class to keep using the pointer beyond the lifetime of SomeObject object. And also it enables the users to change the state of SomeObject object as they wish.
Instead you should refactor your class to include the operations that would be done on the foobar in SomeObject class as methods.
ps. Consider naming your classes properly. When you define it is a class. When you instantiate, then you have an object of that class.
It's generally considered less than ideal to return pointers to internal data at all; it prevents the class from managing access to its own data. But if you want to do that anyway I see no great problem here; it simplifies the management of memory.
Is this bad practice? It seems very hackish.
It is. If the class goes out of scope before the pointer does, the member variable will no longer exist, yet a pointer to it still exists. Any attempt to dereference that pointer post class destruction will result in undefined behaviour - this could result in a crash, or it could result in hard to find bugs where arbitrary memory is read and treated as a BigObject.
if he considered using some smart pointer
Using smart pointers, specifically std::shared_ptr<T> or the boost version, would technically work here and avoid the potential crash (if you allocate via the shared pointer constructor) - however, it also confuses who owns that pointer - the class, or the caller? Furthermore, I'm not sure you can just add a pointer to an object to a smart pointer.
Both of these two points deal with the technical issue of getting a pointer out of a class, but the real question should be "why?" as in "why are you returning a pointer from a class?" There are cases where this is the only way, but more often than not you don't need to return a pointer. For example, suppose that variable needs to be passed to a C API which takes a pointer to that type. In this case, you would probably be better encapsulating that C call in the class.
As long as the caller knows that the pointer returned from getFoobar() becomes invalid when the SomeObject object destructs, it's fine. Such provisos and caveats are common in older C++ programs and frameworks.
Even current libraries have to do this for historical reasons. e.g. std::string::c_str, which returns a pointer to an internal buffer in the string, which becomes unusable when the string destructs.
Of course, that is difficult to ensure in a large or complex program. In modern C++ the preferred approach is to give everything simple "value semantics" as far as possible, so that every object's life time is controlled by the code that uses it in a trivial way. So there are no naked pointers, no explicit new or delete calls scattered around your code, etc., and so no need to require programmers to manually ensure they are following the rules.
(And then you can resort to smart pointers in cases where you are totally unable to avoid shared responsibility for object lifetimes.)
Two unrelated issues here:
1) How would you like your instance of SomeObject to manage the instance of BigObject that it needs? If each instance of SomeObject needs its own BigObject, then a BigObject data member is totally reasonable. There are situations where you'd want to do something different, but unless that situation arises stick with the simple solution.
2) Do you want to give users of SomeObject direct access to its BigObject? By default the answer here would be "no", on the basis of good encapsulation. But if you do want to, then that doesn't change the assessment of (1). Also if you do want to, you don't necessarily need to do so via a pointer -- it could be via a reference or even a public data member.
A third possible issue might arise that does change the assessment of (1):
3) Do you want to give users of SomeObject direct access to an instance of BigObject that they continue using beyond the lifetime of the instance of SomeObject that they got it from? If so then of course a data member is no good. The proper solution might be shared_ptr, or for SomeObject::getFooBar to be a factory that returns a different BigObject each time it's called.
In summary:
Other than the fact it doesn't compile (getFooBar() needs to return const BigObject*), there is no reason so far to suppose that this code is wrong. Other issues could arise that make it wrong.
It might be better style to return const & rather than const *. Which you return has no bearing on whether foobar should be a BigObject data member.
There is certainly no "just" about making foobar a pointer or a smart pointer -- either one would necessitate extra code to create an instance of BigObject to point to.

C++ : Base type member variables as References, or Pointer

I am wondering what might be the best way to accomplish a design dilemma in C++ ...
I have a class, which contains member variables of type Base of another class, and the real objects that are created are created as Derived of Base.
The class does not need to modify these variables, it is only using them. Someone else is creating these variables. These Derived classes also need to go to container (std::vector, QList, etc) classes in my class, so they should perform proper copy construction and assignment.
So, I was wondering what might be the best:
Create the member variables as a Base* and let us manage them and the memory they use. This leads to the classical memory leak issues... Someone just forgets to delete the object when they are not using it anymore.
Create the member variables as a Base& and let's pray that they do not disappear when they go out of scope somewhere.
Having reference member variables is always a poor choice because the compiler generated assignment and move assignment do the wrong thing, or not what one would expect.
Stick to pointers or smart pointers for member variables.
#hansmaad is just right, if you have a problem in controlling life time of the object you should share its ownership with those who create or manage it.
You have 2 options:
1) boost::shared_ptr or std::tr1::shared_ptr
You can easily use this class for any type Base without changing Base, but if you are working in a multi threaded environment it is very hard to achieve thread safety for shared_ptr and do not forget if you create an object as shared using one of this classes you should not manage the life time of the object directly and it is not legal to create a new shared object from raw pointer and you should always copy construct shared object. for example:
boost::shared_ptr<Base> sharedObject( new Drived() );
boost::shared_ptr<Base> validCopy( sharedObject ); // Ok share ownership
Base* p = sharedObject.get();
boost::shared_ptr<Base> invalidCopy( p ); // Error, can't create new shared_ptr from raw pointer
2) boost::intrusive_ptr
You can easily make it thread safe and you can pass it as either raw pointer or smart pointer since it can constructed from raw pointer because reference counting is implemented in the class instead but you should change definition of the class and add you reference counting mechanism
I would go with pointers, both for your vectors (i.e., vector<Base *>, not vector<Base>) and your container class for the following reasons:
If you store the Derived objects in a vector, that vector may get re-sized, which causes all the objects to 'move' to new locations in memory. This would invalidate all outstanding pointers and references
If your container contains references, you are not able to copy it as easily as you would if it contains pointers, as references can only be bound when defined (so in the constructor via MyClass::MyClass(int &a) : memberA(a) {}, if memory serves)
Pointers can be changed via other means such as set methods as needed, and can be set to null in the event of an absence of information
As far as ownership goes, jrok was the first to say it: shared_ptr<> is your friend. Don't reinvent the wheel, just make use of the standard library to simplify things for you. The only thing you would need to worry about in that case is circular pointers (i.e., the object points to itself, so there is always a valid pointer).
The first thing to consider with reference member variables is whether your class (not Derived, the class that's going to have a data member that is a pointer or a reference to Base) needs value semantics (which is another way of saying, "copies and assigns properly").
If so, then reference member variables are more or less out of the question straight away, because they can't be reseated. There are some odd situations where you can use them anyway, but you might as well assume that you won't, and use pointers.
Reference data members are occasionally useful for types that have "entity semantics" (that is, they don't assign at all and may or may not copy), but still they don't gain you a great deal. They can also lure you into the error of writing a constructor that takes a const Base& parameter, and storing it in a reference data member[*].
Who owns the object (and is responsible for freeing it) is completely independent of whether you use a pointer or a reference. There's probably a general convention not to use references for things you own (and there should be a convention not to use raw pointers for things you own, you should choose or write a suitable smart pointer. Smart pointer classes can hold a raw pointer). But that is just convention. You shouldn't assume that you manage the memory if and only if you have a pointer.
Summary: use a pointer, then make a separate decision how the memory is managed.
[*] This is a mistake, because eventually someone will accidentally use a temporary object in an initializer, and then the instance of your class with its reference data member will outlive the temporary. For this reason, things that store references for use after they return shouldn't take const & parameters, even if they don't modify the object. They can take const * instead. In C++11 I suppose they might be OK if there is also an rvalue reference overload, to prevent the const& overload being selected for temporaries, but it's not something I've tried out yet.
You should think about ownership. Whe owns that objects? If there is no clear answer to this questions, you should use a std::shared_ptr<Base> (shared ownership). If there is one class that owns that objects and all others just use them, you could use a std::unique_ptr<Base>, a pointer container like boost::ptr_vector or if there is no polymorphism it that owning classes just the concrete instance. In all other classes you can use plain pointers (prefered as class members) or references (prefered as arguments, if null is not allowed) to that objects.
Case 1 - Shared ownership
class IWorkOnBaseObjects
{
std::vector<std::shared_ptr<Base>> mySubset;
};
class MeToo
{
std::shared_ptr<Base> iNeedThisOne;
};
Case 2
class HomeOfBaseObjects
{
std::vector<std::uniqe_ptr<Base>> baseObjects;
};
class IWorkOnBaseObjects
{
std::vector<Base*> mySubset;
};
Case 3
class A : public Base{};
class B : public Base{};
class HomeOfAObjects
{
std::vector<A> aObjects;
};
class HomeOfBObjects
{
std::vector<B> bObjects;
};
class INeedABaseObject
{
Base* thisOne;
};

dynamic_cast reference to base class in stl container

Is it possible to store a bunch of objects by their base class in say an std::list without pointers. I would really like the objects to be held in the container, then retrieve a pointer to the object in the container and dynamic_cast it to correct derived class.
I have it working fine using pointers. Like (super simple version):
class IComponent
{
virtual ~Icomponent(){}
}
class PositionComponent: public IComponent
{
//...
float x, y;
}
std::list<IComponent*> CList;
//...
// fill the list
// put reference to object in pComponent
//...
PositionComponent* position = dynamic_cast<PositionComponent*>( pComponent)
position->x = 346452.235612;
But the memory management is a huge pain. My actual structure is a
map<enumValue, map<int, IComponent*> >
I get the feeling I can't use the objects themselves because when I add any derived component into the list the extra data will be cut off and leave me with the base class only. This didn't figure this until I tried static_cast instead and it crashed.
Can answer my original question and/or confirm my feelings on the matter. Thanks!
to minimize pain of manual memory management use smart pointers: std::unique_ptr if your compiler already supports it or boost::shared_ptr, but not std::auto_ptr that is not supposed to be used in containers
As you guessed, when you stored an object in a container by value, it gets sliced and the data is chopped off.
If you only need to store one data type (you only show one in your code), then you can make the container hold that type.
If not, you really are stuck using pointers. You can make the memory management much easier by using a smart pointer, or if appropriate, a boost ptr_container of some sort.
Further you might want to think if you need to spend one more iteration considering your design to provide an interface that doesn't require doing a dynamic_cast to get the original type back out again.
Is it possible to store a bunch of objects by their base class in say
an std::list without pointers.
This sentence seems to be contrdicted in C++ point of view IMO. Because STL container can only hold same type of object, if you put derived object into a base type container, it got sliced.
So the apparent normal solution is to use container to hold base type pointers like you did(u could use boost/std smart pointer for memory management)
If you really want to store different objects in one STL container, you may want to consider use boost::any.