Basic polymorphic pointers to base classes - c++

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

Related

Explicitly passing an vector of shared_ptr into a function

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.

c++ why return a reference to a base abstract class

In the class below there is a pointer model_ of type OpModel which is a class. This pointer is initialized in the constructor using new to create an OpModel object. That's fine, you have a pointer to a valid object. The method model() deferences this pointer which access the actual OpModel object. But what I don't understand is that it returns a reference to CompositionalModel which is a different class.
I believe that it is related to polymorphism because OpModel is derived from CompositionalModel, which is an abstract class. But why would you return a reference to the base class?
This is quite a typical thing to do in OO code.
By returning the narrower, base class - think interface - the calling code need only know aboout that.
You can hide all kinds of extra gory, implementation details that way.
Otherwise, any calling code needs to know all about CompositionalModel.
Furthermore, this can change the OpModel to any other type of CompilationUnit and the calling code won't need to change.

Memory management with pointers created using "new" in C++

I have a base class where 2 pointers are declared in the header. The pointers are then initialized with the "new" keyword in a method of the base class and deleted with "delete" in the destructor of the base class.
I also have a derived class that inherits from the base class. I declare a pointer there as well. Depending on a boolean, this pointer is assigned to either pointer of the base class. However, this results in a segfault when the destructor of the base class is called.
My understanding is that this happens because the derived class will delete the pointer automatically before the destructor of the base class is called. When "delete" is called in the base class, then this area of memory has already been freed and a segfault results.
What is the correct way of doing this? My aim is to have a pointer in the derived class that can flexibly equal one of the pointers initialized in the base class.
Either do not delete the pointer in the derived class or use standard smart pointer std::shared_ptr
Your base class should probably have a virtual destructor, then you should override the destructor in your derived class to make sure everything gets deleted in the order you expect.
But it's hard to tell what's happening without seeing the code, so that's just a thought...

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.

A constructor cannot be virtual

In one of the C++ tutorials in internet, i found out the below description on why a constructor cannot be virtual
We cannot declare a virtual constructor. We should specify the exact
type of the object at compile time, so that the compiler can allocate
memory for that specific type.
Is this description correct ?
I am getting confused particularly with the phrase: so that the compiler can allocate
memory for that specific type.
As Bjarne himself explains in his C++ Style and Technique FAQ:
A virtual call is a mechanism to get work done given partial information. In particular, "virtual" allows us to call a function knowing only an interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a "call to a constructor" cannot be virtual.
The constructor cannot be virtual because the standard says so.
The standard says so because it wouldn't make sense. What would a virtual constructor do?
Virtual methods are used in polymorphism... how should polymorphism work if you don't even have the objects yet?
We should specify the exact type of the object at compile time, so
that the compiler can allocate memory for that specific type.
We should specify the exact type at compile time because we want an object of that type... I found their description very confusing too.
Also, in the paragraph it doesn't say this is the reason why constructors can't be virtual. It explains why virtual methods shouldn't be called from the constructor, but that's about it.
How would a constructor be able to be virtual? virtual means that the result to a call to that function is determined by the dynamic type of the object. Before construction, there is no object to do this.
The way the tutorial phrases, what a constructor is, is also bogus. You need to specify the exact type, otherwise the thing you declare wont be considered a constructor and functions without a return type are not allowed.
Just to add to what already been said, there is virtual constructor design pattern, also known as factory method or factory function:
... it deals with the problem of creating objects (products) without specifying the exact class of object that will be created
It is correct, even though it misses the point in my humble opinion.
Constructors set up the virtual dispatching, i.e. point the right pointers at functions of the current class. If constructors could be virtual, who would set up the virtual constructor beforehand? There would be a horrible chicken-and-egg problem.
There is, however, an idiom named "virtual constructor", in which a static member of the class returns a base class pointer with a suitable class:
class A {
static A* create();
virtual ~A();
};
class B : public A { ... };
A* A::create() { return new B(); }