Difference between revisions of "Intermediate C++ Game Programming Tutorial 18"

From Chilipedia
Jump to: navigation, search
(Video Timestamp Index)
(Video Timestamp Index)
 
(14 intermediate revisions by the same user not shown)
Line 92: Line 92:
 
</div>
 
</div>
 
* Presenting the template class <code>Behavior</code> within the class <code>Entity</code> [https://youtu.be/cdOB_gKnJOM?t=15m22s 15:22]
 
* Presenting the template class <code>Behavior</code> within the class <code>Entity</code> [https://youtu.be/cdOB_gKnJOM?t=15m22s 15:22]
* How to transtion between behavioral states? [https://youtu.be/cdOB_gKnJOM?t=16m35s 16:35]
+
* How to transition between behavioral states? [https://youtu.be/cdOB_gKnJOM?t=16m35s 16:35]
 
<div class="mw-collapsible-content">
 
<div class="mw-collapsible-content">
 
** Associate each state with a stack of successor states that are consecutively called
 
** Associate each state with a stack of successor states that are consecutively called
Line 100: Line 100:
 
</div>
 
</div>
 
* The performance impact of using Virtual Functions [https://youtu.be/cdOB_gKnJOM?t=19m36s 19:36]
 
* The performance impact of using Virtual Functions [https://youtu.be/cdOB_gKnJOM?t=19m36s 19:36]
** The direct impact: If you use virtual functions in a class, all objects of that class will have to store a (hidden) pointer to a virtual function table ("v-table")
+
<div class="mw-collapsible-content">
 +
** The direct impact: If you use virtual functions in a class, all objects of that class will have to store a (hidden) pointer to a virtual function table ("vtable")
 
** The v-table holds pointers to code for each virtual function supported by the object. It is used as a lookup table to determine which functions are being called at runtime
 
** The v-table holds pointers to code for each virtual function supported by the object. It is used as a lookup table to determine which functions are being called at runtime
 
** An indirect impact: because the compiler does not know which function will be called at runtime, it can't inline any virtual functions that are being dynamically bound
 
** An indirect impact: because the compiler does not know which function will be called at runtime, it can't inline any virtual functions that are being dynamically bound
** The difference in performance is not problematic, except for specific (rare) cases
+
** The difference in performance is generally not problematic, except for specific (rare) cases
** An example of where performance actually matters: The SpriteEffect system using functors [https://youtu.be/cdOB_gKnJOM?t=21m07s 21:07]
+
</div>
* WORK-IN-PROGRESS
+
* An example of where performance actually matters: The SpriteEffect system [https://youtu.be/cdOB_gKnJOM?t=21m07s 21:07]
 +
<div class="mw-collapsible-content">
 +
** The SpriteEffect system (see [[Intermediate C++ Game Programming Tutorial 14|Intermediate Tutorial 14]]) uses functors to define drawing behavior. These functors are called on heavily as they contain PutPixel calls
 +
** In theory, virtual functions would be nicer, as you could swap out different effects dynamically at runtime (can't do that with a functor).
 +
** However, in that scenario the use of virtual functions would introduce performance issues
 +
** The choice depends on the estimated frequency of function calls (relevant when greater than O(1E6) calls/second)
 +
</div>
 
</div>
 
</div>
  

Latest revision as of 03:55, 15 October 2019

Another two-parter here, and we got the real stuff now. Virtual functions allow you to unlock the true potential of inheritance in C++. You need to know this shit.

Topics Covered

Part 1

  • How to create a virtual function
  • Using the override keyword
  • Creating a pure virtual function
  • Using a container of pointers to manage a heterogeneous collection of objects
  • virtual destructors

Part 2

  • Using inheritance and composition together
  • Basic idea of a polymorphic state machine and its application to entity behavior

Video Timestamp Index

Tutorial 18.1

[Expand]
  • Creating a "Virtual Function" in the MemeFighter class 0:23
  • Enabling "Dynamic Dispatch" by using virtual on the member function in the base class 3:17
  • Applying the override keyword to increase code safety 5:17
  • Making a base class member function "Pure Virtual" using virtual void Func(...) = 0; 7:08
  • We have now applied the concept of "Polymorphism" 9:16
  • Applying Polymorphism to a container of pointers to the shared base type of different derived class objects 9:46
  • Applying Polymorphism to objects created on the heap (dynamic memory management) 13:46
  • "Virtual Destructors": Managing destructors in base and derived classes 14:48
  • Review of termonology and concepts learned 19:49

Tutorial 18.2

[Expand]
  • Design choices in class hierarchy: inheritance vs. composition 0:43
  • Adjusting the MemeFighter code to include the Weapon class 4:20
  • Add feature where one fighter can take the other fighter's weapon 11:36
  • Recap of advantage of the inheritance-composition construct 14:00
  • Presenting the template class Behavior within the class Entity 15:22
  • How to transition between behavioral states? 16:35
  • The performance impact of using Virtual Functions 19:36
  • An example of where performance actually matters: The SpriteEffect system 21:07

Source Code

Inheritance Github Repository

Errata

  • Forgot the virtual destructor for class Weapon! (this one hurts)
  • In the children, the function signatures should be: int CalculateDamage( const Attributes& attr,Dice& d ) const override
  • Though not technically an error, it might have been a better decision to make Weapon::GetName() and Weapon::GetRank() (pure) virtual functions (this would reduce the amount of per-instance data to just the vtable ptr)

See also