diff --git a/content/cpp/concepts/classes/classes.md b/content/cpp/concepts/classes/classes.md index 96dd571a6d6..1bb9286e923 100644 --- a/content/cpp/concepts/classes/classes.md +++ b/content/cpp/concepts/classes/classes.md @@ -113,3 +113,78 @@ This will output: Point(4, 6) Points are equal: false ``` + +# Base class pointers + +A base class pointer gives you the opportunity to create a [pointer](https://github.com/Codecademy/docs/blob/main/content/cpp/concepts/pointers/pointers.md) of type Base, and it can point to any type of class from that hierarchy (it needs to have the Is-A relationship). +If you use [dynamic polymorphism](https://github.com/Codecademy/docs/blob/main/content/cpp/concepts/polymorphism/polymorphism.md), then C++ will know exactly at runtime which function to call (based on the actual object the pointer points to). + + +It's easier to see it work in an example: + +```cpp +#include + +class Base{ +public: + static constexpr const char* message = "Base class. Cats are cute.\n"; + static constexpr int num = 1; + static int x; + virtual void sayHi(){ + std::cout << "Hello from " << message; + std::cout << "The number: " << num << "\n"; + } + //good practice to have virtual destructors if your class uses virtual methods. + virtual ~Base() = default; +}; + +class Derived1 : public Base { +public: + static constexpr const char* message = "Derived 1 class. Indeed they are.\n"; + static constexpr int num = 2; + //this is not called overloading anymore. + //this is called overriding. + virtual void sayHi() override{ + std::cout << "Hello from " << message; + std::cout << "The number: " << num << "\n"; + } +}; + +int Base::x = 999; + +int main(){ + + Base* p1 = new Base(); + Base* p2 = new Derived1(); + p1->sayHi(); + p2->sayHi(); + + std::cout << "\n"; + std::cout << p2->x << "\n"; + std::cout << p1->x << "\n"; + +} +``` + +The output: +```shell +Hello from Base class. Cats are cute. +The number: 1 +Hello from Derived 1 class. Indeed they are. +The number: 2 + +999 +999 +``` + +As you can see: +* **p1** is a pointer of type Base. C++ will dynamically bound it and will use the method from the Base class. +* **p2** is a pointer of type Base that points to a Derived1 Object. Because "sayHi()" is virtual, C++ dynamically triggers the Derived1's own implementation of the "sayHi()" method. + + +## The keywords used: +* override (C++11) - specifies that this method is overridden, means if the signature of the method is **NOT** the same as the one from the base class, the compiler will throw an error **'virtual void Derived1::sayHi()' marked 'override', but does not override'**. +Why do we need this? Because to override methods, the signatures MUST be the same. If the derived method has a different signature, then that's not overriding anymore. +* default (C++11) - uses the compiler-generated version of the virtual destructor. +* static - it's a shared variable, it doesn't participate in polymorphism. Therefore the value will be the same in all instances. +* constexpr (C++11) - specifies that the value of the variable can be evaluated at compile-time.