Explicitly passing an vector of shared_ptr into a function - c++

I have a Base and a number of Derived classes that all define a common method foo. foo is defined with a definition in Base class and is virtual. Derived objects can call Base::foo() in their own foo methods if they wish. Each Derived class has its own set of constructor parameters different from that of the Base class.
I know the terminology is funky but when I say each Derived class I mean there are class definitions like class Parrot: public Base and class Dog: public Base.
I have the following method
void addImportantObjects(std::vector<std::shared_ptr<Base>> objects);
That will eventually save each of those shared pointers to various internal vectors so it can iterate through them and call foo and have the proper foo of the Derived class called.
I am going to be calling this method frequently and I want to get it as small/functional looking and easy to read as possible. Obviously it would be nice to hide away the construction of the vector or the pointer casts if possible.
This is the best I have been able to do thus far
std::vector<std::shared_ptr<Base>> objs;
objs.push_back(std::dynamic_pointer_cast<Base>(std::make_shared<Derived>(args)));
objs.push_back(std::dynamic_pointer_cast<Base>(std::make_shared<Derived2>(args)));
addImportantObjects(objs);
You can see a lot of space is wasted with the casting and the push_backs and the shared pointer syntax. If I had a long list of objects I wished to add it would be be a lot of code.
My question is there any way I could make it look more closer to perhaps
addImportantObjects({Derived(args), Derived2(args)})
In case it is important here these objects will not be referenced outside of the scope of the object with the addImportantObjects method. The shared pointer is just to ensure that internally it does not copy anything as it processes it. Any method that allows this to happen but does not copy the object more than once would be ok.

Related

C++ how to create a array of subclass use baseclass

suppose I have three class like these:
class base {
//some data
method();
};
class sub1 : base {
//some data
//overrides base method
method();
};
class sub2: base {
//some data
//overrides base methods
method();
};
How can I create a array mixed with sub1 and sub2? then calling subclass method with base?
Ok, let's sort this out. First of all, you probably meant virtual method();, probably with a return type, maybe with parameters. Without virtual, base class pointers and references won't know about the overridden method. Second, make the destructor virtual. Do this until you know why you need to (delete (base*) new derived;) - then keep doing this until all your neighbourhood knows why you need to. Third, the sad thing is, all std. C++ containers are homogeneous (non-std. heterogeneous container-like objects in Boost exist), thus you need to find an object that's common and that's somehow able to handle these types. Common choices are:
Common base class pointer, in your case, base*. This conventionally owns the objects and is manually (de)allocated (that is, you need to call new and delete). This is the most common choice. You might try smart pointers later, but let's get the basics first.
Common base class reference, in your case, base&. Common convention is that this doesn't own the object (albeit this is not a language restriction), thus it's mainly used for referring to objects that are stored in another container. Since you need to store them somewhere, I wouldn't opt for this now, but it might come handy later.
std::variant<> (or boost::variant<>), this is a discriminated union, that is, a class that stores one and only one of the listed items and knows which one it stores. You don't need a common base class, but even if you have one, it's cool because it tends to store objects locally, thus might be faster when you have enough cache.
union, which is like variant, but does not know the type being stored. Local storage is guaranteed, as well as UB if you write one field and read another
Compiler-specific solutions. If you know that your classes are of the same size (in this case, they are) and you know for sure that you have untyped memory, then you might store the base class and it'll 'just work', provided you always take the address and -> operator. Note that this is UB squared, I just list this because you'll likely encounter similar code. Also note that simply having a union does not remove UB in this case - until we have access to virtual table pointer, this can only be done by manually handling virtual functions.

Object slicing within a two-dimensional array in c++

Hello I am having a small issue with storing derived type objects within a 2-dimensional array of the base type without loosing the derived type stored in the array.
For example there is the following Base and Derived class:
class Base{
}
class Derived: public Base{
}
There is a point where I have a Base object created like the following:
Base objectB;
Then I cast the above object to the type of the Derived class like the following:
Base *referencePointer = &objectB;
Derived *derivedPointer = static_cast<Derived*>(referencePointer);
At this point everything is working correctly (if I print out the type of derivedPointer it is of type Derived).
Now I have a 2 dimensional array of type Base class initialized as the following:
Base *baseArray[5][5];
Now I input the derivedPointer value into the array as the following:
baseArray[x][y] = derivedPointer;
This is where the problem occurs as it stores in the referencePointer but it becomes of Base type (object slicing) and I am unsure as to how I would go about storing the referencePointer value and keep its type within an array of type Base.
Any help is much appreciated,
Thank you!
video game with different types of players that are able to move
different based on there type but they all have certain base
functionality that are the same.
Imagine that the 'certain base functionality' is implemented in the base class. These methods can easily be made available to any derived classes as public or protected methods. Thus eliminating duplicate code.
Now imagine the base class provides a virtual method "void move(CoordinatesXYZ_t to, VelocityXYZ_t vel, AccelerationXYZ_t acc)".
Simply by adding a (virtual) method with the same signature in a derived class, each derived object can provide their own unique response to the gaming engine's move command. There is no need for the gaming engine to know what type of derived object it is, the correct virtual method will be invoked.
Downcast'ing is simply not needed. The game engine can be written so that it simply does not need to care what kind of derived class it is dealing with - as long as the derived object conforms to the interface. The game engine invokes a virtual method, which will result in the invocation of the appropriate derived object method.
The actual method can be unique for every member of the 2 dimensional array of base pointers.
The actual method can even do nothing (i.e. a tree probably does not move.)
And the derived class does not have to provide a move method unless the desired behaviour is different from what the base class' move method provides.
Derived *derivedPointer = static_cast<Derived*>(referencePointer);
This is a mistake because referencePointer actually points to a Base object. The compiler won't magically tack on extra bits to the Base object to turn it into a Derived object. To avoid this error, use dynamic_cast instead of static_cast. Then you will be able to detect failure.
Note, Base needs to be polymorphic for this to work, it must have at least 1 virtual function.
By the way, this is nothing to do with slicing. Even if referencePointer pointed to a Derived, that's fine: you have a 2-D array of pointers, it's fine to put in a Base *, which might point to an object of Derived type. Slicing would be if you had a 2-D array of Base.

Basic polymorphic pointers to base classes

While I've been working in c++ for a while, I haven't had need to use polymorphic features until now, and I'm very intrigued by them.
If I have a base class ClassA and another ClassB derives from it, I understand that I can have virtual member function in ClassA that, when implemented in ClassB, will be called in a ClassB instance even if that instance is pointed at using a ClassA pointer. Without this virtual keyword, I presume the base class implementation would prevail when using a base class pointer, yet be operating on an object that was instantiated from the subclass, which seems questionable to me if in fact ClassB has its own implementation of the same function that is effectively ignored in such a case.
Is this a correct understanding of polymorphic behavior?
Now the real question is how do you refer to ClassB using a pointer to is base class. I can really only think of two ways:
Create the pointer at the time of instantiation, using a function that returns a base class pointer while actually allocating memory for the subclass instead, using the subclass's constructor. (Does such a creation function have a common name?)
Casting an object using static_cast and assigning it to a pointer to the base class.
Are these the two main techniques for generating base class pointers to objects of a subclass?
The easiest way is to simply assign it, no cast necessary:
ClassA *ptrA = new ClassB;
You're correct that you need the virtual keyword to enable polymorphic behavior. Here's one way to think about it. C++ operates on the static type of an object. When you call ptrA->foo(), the type of the pointer is ClassA*. If that function is not declared virtual, then it will blindly call ClassA's version of the function. There's no other choice. But if foo() is virtual, then it knows to stop and ask, "Wait, what type am I really?" And the answer in that case is ClassB, so it will call ClassB's version.
Also note that you don't need pointers to achieve this. Another common way you'll see polymorphism in action is via a function call:
void bar(ClassA &aObj)
{
aObj.foo();
}
// ...
ClassB bObj;
bar(bObj);

c++ casting base class to derived class mess

If I were to create a base class called base and derived classes called derived_1, derived_2 etc... I use a collection of instances of the base class, then when I retrieved an element and tried to use it I would find that C++ thinks it's type is that of the base class, probably because I retrieved it from a std::vector of base. Which is a problem when I want to use features that only exist for the specific derived class who's type I knew this object was when I put it into the vector.
So I cast the element into the type it is supposed to be and found this wouldn't work.
(derived_3)obj_to_be_fixed;
And remembered that it's a pointer thing. After some tweaking this now worked.
*((derived_3*)&obj_to_be_fixed);
Is this right or is there for example an abc_cast() function that does it with less mess?
edit:
I had to expand this into another question, the full solutions are shown there. stackoverflow.com ... why-the-polymorphic-types-error-and-cleanup-question
If you store your objects in a std::vector<base> there is simply no way to go back to the derived class. This is because the derived part has been sliced of when storing it in an instance of base class (afterall your vector contains copies of your data, so it happily copies only the base part of your objectes), making the stored object a true instance of base class, instead of a derived class used as a base class.
If you want to store polymorphic objects in the vector make it a std::vector<base*> (or some kind of smartpointer to base, but not base itself) and use dynamic_cast<derived_3*> to cast it to the correct type (or static_cast, if its performance sensitive and you are confident enough that you are trying to cast to the correct type (in that case horrible things will happen if you are wrong, so beware)).
If you are using a vector of base then all your instances are base instances and not derived instances.
If you try to insert a derived instance, the object will be sliced. Inserting into a vector always involves a copy and the target type is determined by the type of the object that the vector holds. A vector cannot hold objects of different types.
Most of the time you shall not need to do this. A carefully designed class hierarchy can handle this by polymorphism (i.e. virtual functions).
If you really need to cast to the derived type, use dynamic_cast operator.
What you are trying to do is not even remotely possible. If the objects stored in your container have type base, then they are base, period. They are not derived objects, they will never become derived objects and they cannot be used as derived objects regardless of what you do.
Your cast through pointers is nothing than just a hack that reinterprets memory occupied by base object as derived object. This is totally meaningless and can only "work" by accident.

Use of derived class construction when derived class object is type compatible with base class

class baseClass{};
class derivedClass : public baseClass{};
baseClass *obj = new derivedClass ; // For simplicity, I amn't providing any-
// class members.
Though, baseClass and derivedClass construction takes place, derivedClass members are opaque to obj. Then, what is the use of derivedClass construction. BTW, I understand that derivedClass constructor invokes baseClass constructor and upon return derivedClass construction should take place. What is use of it anyway ? Just curious to know why it is so designed :)
In a word, polymorphism. In more words, in a system where multiple classes are derived from a common base class it's the ability to treat objects of different derived classes in the same way, without worrying about their actual type.
Consider a drawing package that manages various shapes. You may choose to use an abstract base class called Shape that implements common methods such as Draw(), and perhaps has some common data members common to all shapes like x-pos and y-pos. You may then create some derived concrete classes like Ellipse and Square, which will take their own shape-specific constructor parameters and override the Draw() method from the abstract class. The Circle constructor might need x-pos, y-pos and radius, for example; it will use the radius parameter itself, but pass the x-pos and y-pos arguments to the inherited constructor.
You could then implement a Drawing() class that acts as a container of various Shapes, and iterate through that container to render your drawing without ever worrying about the actual type of the specific Shapes you're drawing.
The rationale behind why derivedClass members get initialized is because if derivedClass has any virtual functions that override those declared in baseClass and those members reference data members of derivedClass, the initialization must occur or, when those functions are invoked, the results will be undefined.
In general, you won't be using inheritance unless you are trying to have polymorphic classes. If the derived classes couldn't have their own state, then the base class would have to guess all of the possible data needed in derived classes, which would be a brittle, fragile approach to design.