commit a4f7e614f1594f6e47ad5ef3944e489a3c441b9d Author: Redacted Date: Sat Feb 8 20:21:42 2025 -0500 Initial commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..04db1e5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.18) +project(polymorphism) + +if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) + message(FATAL_ERROR "In-Source builds are not allowed") +endif() + +set(CMAKE_CXX_STANDARD 20) + +file(GLOB_RECURSE HEADERS "include/*.h") + +file(GLOB_RECURSE SOURCES "src/*.cpp" "main.cpp") + +include_directories("include") + +add_executable(polymorphism ${SOURCES}) + +set_target_properties(polymorphism PROPERTIES LINKER_LANGUAGE CXX) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/include/polymorphicClass.h b/include/polymorphicClass.h new file mode 100644 index 0000000..1ba85cc --- /dev/null +++ b/include/polymorphicClass.h @@ -0,0 +1,21 @@ +#pragma once + +class BaseClass { +protected: + bool b; + float f1; + float f2; +public: + virtual void printClassName(); //For a class to be "polymorphic", You *must* have at-least one virtual member. + virtual ~BaseClass() = default; //If you don't have any reason to have virtual functions, you can make a virtual destructor. +}; //Virtual has a ton of uses. The *huge* one is the ability to use dynamic cast. -> someFunc.cpp + +class DerivedClass1 : public BaseClass { +public: + void printClassName() override; //Using "Virtual Functions" we "Override" the function inside the base class. -> polymorphicClass.cpp +}; + +class DerivedClass2 : public BaseClass { +public: + void printClassName() override; +}; \ No newline at end of file diff --git a/include/someFunc.h b/include/someFunc.h new file mode 100644 index 0000000..fe21132 --- /dev/null +++ b/include/someFunc.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void someFunc(BaseClass* bC); \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6523362 --- /dev/null +++ b/main.cpp @@ -0,0 +1,29 @@ +#include + +auto* b = new BaseClass; //Allocate an instance of each class from the heap, +auto* dc1 = new DerivedClass1; //Doing this is *really* slow compared to the stack. +auto* dc2 = new DerivedClass2; //But it's fantastic for things you'll allocate once and use a LOT. + +int main() { //Look at polymorphicClass.h. + someFunc(b); + someFunc(dc1); + someFunc(dc2); + + delete b; //Delete them when you're done so that you don't mem-leak. + delete dc1; + delete dc2; + + //b->printClassName(); //Don't access them after you delete them. + //This is called a "use after free" and is very bad. + return 0; +} + +#pragma region windows +#ifdef _WIN32 +extern "C" { + int wmain(int argc, wchar_t* argv[]) { + return main(); + } +} +#endif +#pragma endregion \ No newline at end of file diff --git a/src/polymorphicClass.cpp b/src/polymorphicClass.cpp new file mode 100644 index 0000000..0c36dc9 --- /dev/null +++ b/src/polymorphicClass.cpp @@ -0,0 +1,13 @@ +#include +#include +void BaseClass::printClassName() { //The function in the base class. + std::cout << "Base Class" << std::endl; +} + +void DerivedClass1::printClassName() { //The overridden version of the same function. + std::cout << "Derived Class 1" << std::endl; //These create "Virtual Function Table" entries. +} //The V-Table stores pointers to which version of the function should be run for each derived class. + //You can also specifically run the version from the Base Class. In this case, BaseClass::printClassName(); +void DerivedClass2::printClassName() { + std::cout << "Derived Class 2" << std::endl; +} diff --git a/src/someFunc.cpp b/src/someFunc.cpp new file mode 100644 index 0000000..566c2f0 --- /dev/null +++ b/src/someFunc.cpp @@ -0,0 +1,18 @@ +#include +#include + +void someFunc(BaseClass* bC) { //We can take the BaseClass as a function parameter, Which also allows us to accept any of the derived classes. + if (auto* dc1 = dynamic_cast(bC)) { //If we passed in DerivedClass1. + std::cout << "You passed in "; dc1->printClassName(); //The overridden version of the function from DerivedClass1 will run. + return; //Exit the void function early. + } + + if (auto* dc2 = dynamic_cast(bC)) { + std::cout << "You passed in "; dc2->printClassName(); + return; + } + + if (auto* b = dynamic_cast(bC)) //If we passed in the base class and not any derived class. + //*Must* be checked for last if you'll be passing in BaseClass because this will always succeed. + std::cout << "You passed in ", b->printClassName(); +}