NOTE: The source code, as presented in the video, might cause compilation errors with the newer MDK-ARM / uVision toolsets. This is because the underlying compiler in MDK-ARM has been changed to "Compiler-6", while the older "Compiler-5" is considered now obsolete. The updated code that compiles cleanly with "Compiler-6" is available from the companion website at: www.state-machine.com/video-course and from GitHub: github.com/QuantumLeaps/modern-embedded-programming-course
"Since the pointer might be actually upcast from a derived class". Actually, a pointer can point to anything that has a physical address, so it might be casted to point to anything. The flexibility of polymorphism is an application of the flexibility of pointers. Everything is in the memory, so everything has a physical address, hence it can be manipulated by pointers.
Of course, the C and C++ programming languages allow you to perform all sorts of crazy pointer casts. We don't need to debate this. But when I said "a pointer might be upcast from a derived class", I meant that the upcast is *safe* and *legitimate* . --MMS
@@StateMachineCOM Yes, Sir. I quoted your words because it helps me to grasp the key logic behind all those tricks and very much admired your ability to make things crystal clear. Thank you so much for sharing!
Thanks for another insightful video on polymorphism. I have a quick question. Instead of defining the array of shape pointer and initializing with pointer to the object of derived class, is it possible to declare one shape pointer in the drawGraph method and then assign it with derived class pointer object(like rectangle and circle) and then invoke virtual method(like draw)? Basically, we are upcasting multiple times on same type of pointer and get the same behavior.
Why don't you try to implement your suggestion? Then you will understand why it cannot work. The problem is that the object types are *not known* in a function like drawGraph(). If the type was known, you could skip the whole business of virtual pointers and call the appropriate implementation, like Circle_draw(), directly. --MMS
@@StateMachineCOM - I built the code and ran in simulation mode. Here is my change. /* draw all shapes in a given array graph[] */ void drawGraph(Shape *graph[]) { for (std::uint8_t i = 0; graph[i] != (Shape *)0; ++i) { Shape *ps = graph[i]; ps->draw(); /* polymorphism! */ //graph[i]->draw(); } } This code gives the same behavior as the original code. So I did not understand why you think it will not work?
@@jankeshchakravarthy9389, I misunderstood your first comment and didn't think you meant the trivial introduction of a temporary pointer. My confusion was about your upcasting comments. So, just to clarify, there is NO upcasting in the drawGraph() function, with or without the temporary pointer. All the pointers are of type Shape. --MMS
Hello Miro, this is the best teaching video series ever! Thank you. I have a bit off-topic question. You almost always type numeric constants with the type specifier, e.g. while (counter > 0U), but sometimes you violate this rule, e.g. Shape s2(3, 4). Is there any special reason for it?
Important Note: void SysTick_Handler(void) -> extern "C" void SysTick_Handler(void) and void GPIOF_Handler(void) to extern "C" void GPIOF_Handler(void) otherwise Keil wont find the handler and will run the weak handlers in the start up cod
NOTE: The source code, as presented in the video, might cause compilation errors with the newer MDK-ARM / uVision toolsets. This is because the underlying compiler in MDK-ARM has been changed to "Compiler-6", while the older "Compiler-5" is considered now obsolete. The updated code that compiles cleanly with "Compiler-6" is available from the companion website at:
www.state-machine.com/video-course
and from GitHub:
github.com/QuantumLeaps/modern-embedded-programming-course
Being a java programmer, it gives great sense of satisfaction knowing how everything works at low level. Thanks man, keep sharing your knowledge!
it is my pleasure to join this great channel with Mr Miro, thanks a lot for this highly effort work
Have been waiting for it! Thanks!
You are the best Miro! Thanks a lot for making video
Hello Miro, please continue posting new lessons. The video you posted are best lessons i ever had in my career. Thanks so much
Brilliant video 😍
Happy New Year, Miro!
Really look forward to see the coming lectures!
Thank you Dr. Miro
great video thank you for posting.
I know "Application Note Object-Oriented Programming in C" already, nonetheless I'm looking forward to next lesson :-)
"Since the pointer might be actually upcast from a derived class". Actually, a pointer can point to anything that has a physical address, so it might be casted to point to anything. The flexibility of polymorphism is an application of the flexibility of pointers. Everything is in the memory, so everything has a physical address, hence it can be manipulated by pointers.
Of course, the C and C++ programming languages allow you to perform all sorts of crazy pointer casts. We don't need to debate this. But when I said "a pointer might be upcast from a derived class", I meant that the upcast is *safe* and *legitimate* . --MMS
@@StateMachineCOM Yes, Sir. I quoted your words because it helps me to grasp the key logic behind all those tricks and very much admired your ability to make things crystal clear. Thank you so much for sharing!
Thanks for another insightful video on polymorphism. I have a quick question. Instead of defining the array of shape pointer and initializing with pointer to the object of derived class, is it possible to declare one shape pointer in the drawGraph method and then assign it with derived class pointer object(like rectangle and circle) and then invoke virtual method(like draw)? Basically, we are upcasting multiple times on same type of pointer and get the same behavior.
Why don't you try to implement your suggestion? Then you will understand why it cannot work. The problem is that the object types are *not known* in a function like drawGraph(). If the type was known, you could skip the whole business of virtual pointers and call the appropriate implementation, like Circle_draw(), directly. --MMS
@@StateMachineCOM - I built the code and ran in simulation mode. Here is my change.
/* draw all shapes in a given array graph[] */
void drawGraph(Shape *graph[]) {
for (std::uint8_t i = 0; graph[i] != (Shape *)0; ++i) {
Shape *ps = graph[i];
ps->draw(); /* polymorphism! */
//graph[i]->draw();
}
}
This code gives the same behavior as the original code. So I did not understand why you think it will not work?
@@jankeshchakravarthy9389, I misunderstood your first comment and didn't think you meant the trivial introduction of a temporary pointer. My confusion was about your upcasting comments. So, just to clarify, there is NO upcasting in the drawGraph() function, with or without the temporary pointer. All the pointers are of type Shape. --MMS
Hey, when come the next ?
Hello Miro, this is the best teaching video series ever! Thank you.
I have a bit off-topic question. You almost always type numeric constants with the type specifier, e.g. while (counter > 0U), but sometimes you violate this rule, e.g. Shape s2(3, 4). Is there any special reason for it?
The suffix 'U' in numerical literals is mostly important in expressions (which includes logical expressions with '>', '
@@StateMachineCOM Thank you for the explanation. Pavel Palivec
Important Note:
void SysTick_Handler(void) -> extern "C" void SysTick_Handler(void)
and
void GPIOF_Handler(void) to extern "C" void GPIOF_Handler(void)
otherwise Keil wont find the handler and will run the weak handlers in the start up cod