diff --git a/notebooks/Overloading.ipynb b/notebooks/Overloading.ipynb index 5e02d6af8998d9a16cfeee8511f47f5c24d3d5ef..7800c7ee8b7eef2baad15ca4b8159a6fd5d53513 100644 --- a/notebooks/Overloading.ipynb +++ b/notebooks/Overloading.ipynb @@ -1 +1 @@ -{"metadata":{"orig_nbformat":4,"language_info":{"codemirror_mode":"text/x-c++src","file_extension":".cpp","mimetype":"text/x-c++src","name":"c++","version":"17"},"kernelspec":{"name":"xcpp17","display_name":"C++17","language":"C++17"}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Overloading\n\nIn C++ functions that expect different types or numbers of parameters can still have the same name. This is called **overloading** and constitues a form of **static polymorphism**.","metadata":{"tags":[]},"id":"235e90d0-cc51-48c6-9df4-399338da447a"},{"cell_type":"markdown","source":"### Example #1\nWe are going to implement two free-functions that return the magnitude of their argument.","metadata":{},"id":"90ce7880-230c-4723-bbb0-09bb0ce9be7e"},{"cell_type":"code","source":"// Version for int\nint getMagnitude( int input ) {\n return input > 0 ? input : -input;\n}","metadata":{"trusted":true},"execution_count":22,"outputs":[],"id":"eec83314-77dd-473c-9350-74d59ee80a28"},{"cell_type":"code","source":"// Version for double\ndouble getMagnitude( double input ) {\n return input > 0.0 ? input : -input;\n}","metadata":{"trusted":true},"execution_count":23,"outputs":[],"id":"bdf6437f-1345-4341-89ad-2e1bfccf3f51"},{"cell_type":"code","source":"// A driver to check that this works\nint main() {\n double dVal = -5.2;\n std::cout << \"|\" << dVal << \"| = \" << getMagnitude( dVal )\n << \", |2| = \" << getMagnitude( 2 ) << std::endl;\n}","metadata":{"trusted":true},"execution_count":24,"outputs":[],"id":"b729878a-62d9-4f61-89c5-a4cdaba10d17"},{"cell_type":"markdown","source":"Let's execute our program. In our notebook we can do this by invoking the main() function:","metadata":{},"id":"5b6c893e-1883-482c-8415-0ccdebfba63d"},{"cell_type":"code","source":"main()","metadata":{"trusted":true},"execution_count":25,"outputs":[{"name":"stdout","text":"|-5.2| = 5.2, |2| = 2\n","output_type":"stream"},{"execution_count":25,"output_type":"execute_result","data":{"text/plain":"0"},"metadata":{}}],"id":"7ee16102-554c-45c2-8355-dc68d10b2243"},{"cell_type":"markdown","source":"What's the last line with the 0?","metadata":{},"id":"3b86fe70-835c-4358-9c46-f1b582327fa0"},{"cell_type":"markdown","source":"### Example #2","metadata":{},"id":"6a52697f-6c1b-4561-8626-a56a75d80f75"},{"cell_type":"markdown","source":"A simple function that echos its input to standard output","metadata":{},"id":"d418a230-01d8-4d6b-a24b-c16bb3211f27"},{"cell_type":"code","source":"void display( const std::string mesg ) {\n std::cout << mesg << std::endl;\n}","metadata":{"trusted":true},"execution_count":26,"outputs":[],"id":"4229aeb8-1ec6-4fe1-b7fd-6a2fe4573255"},{"cell_type":"markdown","source":"Another version of display() which differs from the former in:\n- expects a 2nd argument\n- indents the string by depth blanks","metadata":{},"id":"4f81e8dd-ee8c-4714-b9ae-a40e0099e671"},{"cell_type":"code","source":"void display( const std::string mesg, int depth ) {\n std::string indent( depth, ' ' );\n std::cout << indent << mesg << std::endl;\n}","metadata":{"trusted":true},"execution_count":27,"outputs":[],"id":"c224bdfb-91a2-4519-acfb-183864ab4726"},{"cell_type":"markdown","source":"Let's use both to do some simple drawing","metadata":{},"id":"4468de2f-f108-41b2-a8c5-2d4c49d79987"},{"cell_type":"code","source":"int main() {\n const int len = 5;\n std::string stars( len, '*' );\n display( stars );\n for( unsigned int k = 1; k < stars.length(); k++ ) {\n display( stars.substr( k ,std::string::npos ), k );\n }\n}\n\nmain()","metadata":{},"execution_count":null,"outputs":[{"name":"stdout","text":"*****\n ****\n ***\n **\n *\n","output_type":"stream"},{"execution_count":28,"output_type":"execute_result","data":{"text/plain":"0"},"metadata":{}}],"id":"d1acaf75-c148-4aa8-a407-d2391a64fd33"},{"cell_type":"markdown","source":"### Example #3\nWe want to implement two functions that return a zero for initialising new variables.","metadata":{},"id":"e381e911-aa5c-43bd-a3d5-2c25a7a0ab3e"},{"cell_type":"markdown","source":"The magic command **%%file** will write the contents of the cell to the given file","metadata":{},"id":"482d9fcc-e25f-4be2-883c-8c10e7b0ffaf"},{"cell_type":"code","source":"%%file example.cpp\nint zero() {\n return 0;\n}\n\ndouble zero() {\n return 0.0;\n}\n\nint main() {\n double dVal = zero();\n int iVal = zero();\n}","metadata":{"trusted":true},"execution_count":35,"outputs":[{"name":"stdout","text":"Overwriting example.cpp\n","output_type":"stream"}],"id":"a0160540-141d-49a8-a16b-0832deb45111"},{"cell_type":"markdown","source":"Now let's check whether GCC will compile it?","metadata":{},"id":"5e2ece20-14ea-4eab-b147-c2056abcb54d"},{"cell_type":"code","source":"!g++ example.cpp","metadata":{"trusted":true},"execution_count":36,"outputs":[{"name":"stdout","text":"example.cpp: In function ‘double zero()’:\nexample.cpp:5:8: error: ambiguating new declaration of ‘double zero()’\n double zero() {\n ^~~~\nexample.cpp:1:5: note: old declaration ‘int zero()’\n int zero() {\n ^~~~\n","output_type":"stream"}],"id":"ecd5b116-b2f7-453f-9bdf-fd4d424f5161"},{"cell_type":"markdown","source":"Wasn't aware that 'ambiguate' was a noun ;-) Let's see what clang will tell us","metadata":{},"id":"2c71fc09-d97c-4f25-ba9e-cd013edda551"},{"cell_type":"code","source":"!clang++ example.cpp","metadata":{"trusted":true},"execution_count":37,"outputs":[{"name":"stdout","text":"example.cpp:5:8: error: functions that differ only in their return type cannot be overloaded\ndouble zero() {\n~~~~~~ ^\nexample.cpp:1:5: note: previous definition is here\nint zero() {\n~~~ ^\n1 error generated.\n","output_type":"stream"}],"id":"3cb990eb-aef8-464b-ac85-644c0d7b57c2"},{"cell_type":"markdown","source":"Okay, so apparently overloading does not work, for **'functions that differ only in their return type'**.\nWell, we might remember that the **signature of a function** consists of the number and type of its arguments, but not its return type.\nWe can check on that by the following:","metadata":{},"id":"1e494c0f-d7a1-4412-b67b-5911f5d7d46b"},{"cell_type":"code","source":"%%file signature.cpp\n\nint getMagnitude( int input ) {\n return input > 0 ? input : -input;\n}\n\ndouble getMagnitude( double input ) {\n return input > 0.0 ? input : -input;\n}\n\nint getMagnitude( short input ) {\n return input > 0 ? input : -input;\n}\n\nvoid demo( double dVal, float fVal, int* iPtr ){};","metadata":{"trusted":true},"execution_count":56,"outputs":[{"name":"stdout","text":"Overwriting signature.cpp\n","output_type":"stream"}],"id":"91797c03-d79d-446d-946a-1ecdd8184f44"},{"cell_type":"code","source":"!g++ -c signature.cpp","metadata":{"trusted":true},"execution_count":57,"outputs":[],"id":"07ca2086-0fc4-41df-8061-40aa13bc7f67"},{"cell_type":"code","source":"!nm -C signature.o","metadata":{"trusted":true},"execution_count":58,"outputs":[{"name":"stdout","text":"0000000000000014 T getMagnitude(double)\n0000000000000000 T getMagnitude(int)\n0000000000000046 T getMagnitude(short)\n000000000000005b T demo(double, float, int*)\n","output_type":"stream"}],"id":"773be3ed-09bb-48bc-9af6-75a6156db75c"},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[],"id":"275f2c22-6b23-45bd-b628-7d2b998a8da5"}]} \ No newline at end of file +{"cells":[{"metadata":{"tags":[]},"id":"235e90d0-cc51-48c6-9df4-399338da447a","cell_type":"markdown","source":"# Overloading\n\nIn C++ functions that expect different types or numbers of parameters can still have the same name. This is called **overloading** and constitues a form of **static polymorphism**."},{"metadata":{},"id":"90ce7880-230c-4723-bbb0-09bb0ce9be7e","cell_type":"markdown","source":"### Example #1\nWe are going to implement two free-functions that return the magnitude of their argument."},{"metadata":{"trusted":true},"id":"eec83314-77dd-473c-9350-74d59ee80a28","cell_type":"code","source":"// Version for int\nint getMagnitude( int input ) {\n return input > 0 ? input : -input;\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"id":"bdf6437f-1345-4341-89ad-2e1bfccf3f51","cell_type":"code","source":"// Version for double\ndouble getMagnitude( double input ) {\n return input > 0.0 ? input : -input;\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"id":"b729878a-62d9-4f61-89c5-a4cdaba10d17","cell_type":"code","source":"// A driver to check that this works\n#include <iostream>\n\nint main() {\n double dVal = -5.2;\n std::cout << \"|\" << dVal << \"| = \" << getMagnitude( dVal )\n << \", |2| = \" << getMagnitude( 2 ) << std::endl;\n}","execution_count":null,"outputs":[]},{"metadata":{},"id":"5b6c893e-1883-482c-8415-0ccdebfba63d","cell_type":"markdown","source":"Let's execute our program. In our notebook we can do this by invoking the main() function:"},{"metadata":{"trusted":true},"id":"7ee16102-554c-45c2-8355-dc68d10b2243","cell_type":"code","source":"main()","execution_count":null,"outputs":[]},{"metadata":{},"id":"3b86fe70-835c-4358-9c46-f1b582327fa0","cell_type":"markdown","source":"What's the last line with the 0?"},{"metadata":{},"id":"6a52697f-6c1b-4561-8626-a56a75d80f75","cell_type":"markdown","source":"### Example #2"},{"metadata":{},"id":"d418a230-01d8-4d6b-a24b-c16bb3211f27","cell_type":"markdown","source":"A simple function that echos its input to standard output"},{"metadata":{"trusted":true},"id":"4229aeb8-1ec6-4fe1-b7fd-6a2fe4573255","cell_type":"code","source":"void display( const std::string mesg ) {\n std::cout << mesg << std::endl;\n}","execution_count":null,"outputs":[]},{"metadata":{},"id":"4f81e8dd-ee8c-4714-b9ae-a40e0099e671","cell_type":"markdown","source":"Another version of display() which differs from the former in:\n- expects a 2nd argument\n- indents the string by depth blanks"},{"metadata":{"trusted":true},"id":"c224bdfb-91a2-4519-acfb-183864ab4726","cell_type":"code","source":"void display( const std::string mesg, int depth ) {\n std::string indent( depth, ' ' );\n std::cout << indent << mesg << std::endl;\n}","execution_count":null,"outputs":[]},{"metadata":{},"id":"4468de2f-f108-41b2-a8c5-2d4c49d79987","cell_type":"markdown","source":"Let's use both to do some simple drawing"},{"metadata":{"trusted":true},"id":"d1acaf75-c148-4aa8-a407-d2391a64fd33","cell_type":"code","source":"int main() {\n const int len = 15;\n std::string stars( len, '*' );\n display( stars );\n for( unsigned int k = 1; k < stars.length(); k++ ) {\n display( stars.substr( k, std::string::npos ), k );\n }\n}\n\nmain()","execution_count":null,"outputs":[]},{"metadata":{},"id":"b518bf97-ab4e-4fbb-90cb-efb9dde87f6f","cell_type":"markdown","source":"If we do not know about some standard C++ function or object, we can ask for help:"},{"metadata":{"trusted":true},"id":"79748a7a-6695-4ac0-b1a2-b3de4610d3c6","cell_type":"code","source":"?std::string","execution_count":null,"outputs":[]},{"metadata":{},"id":"e381e911-aa5c-43bd-a3d5-2c25a7a0ab3e","cell_type":"markdown","source":"### Example #3\nWe want to implement two functions that return a zero for initialising new variables."},{"metadata":{},"id":"482d9fcc-e25f-4be2-883c-8c10e7b0ffaf","cell_type":"markdown","source":"The magic command **%%file** will write the contents of the cell to the given file"},{"metadata":{"trusted":true},"id":"a0160540-141d-49a8-a16b-0832deb45111","cell_type":"code","source":"%%file example.cpp\nint zero() {\n return 0;\n}\n\ndouble zero() {\n return 0.0;\n}\n\nint main() {\n double dVal = zero();\n int iVal = zero();\n}","execution_count":null,"outputs":[]},{"metadata":{},"id":"5e2ece20-14ea-4eab-b147-c2056abcb54d","cell_type":"markdown","source":"Now let's check whether GCC will compile it?"},{"metadata":{"trusted":true},"id":"ecd5b116-b2f7-453f-9bdf-fd4d424f5161","cell_type":"code","source":"!g++ example.cpp","execution_count":null,"outputs":[]},{"metadata":{},"id":"2c71fc09-d97c-4f25-ba9e-cd013edda551","cell_type":"markdown","source":"Wasn't aware that 'ambiguate' was a noun ;-) Let's see what clang will tell us"},{"metadata":{"trusted":true},"id":"3cb990eb-aef8-464b-ac85-644c0d7b57c2","cell_type":"code","source":"!clang++ example.cpp","execution_count":null,"outputs":[]},{"metadata":{},"id":"1e494c0f-d7a1-4412-b67b-5911f5d7d46b","cell_type":"markdown","source":"Okay, so apparently overloading does not work, for **'functions that differ only in their return type'**.\nWell, we might remember that the **signature of a function** consists of the number and type of its arguments, but not its return type.\nWe can check on that by the following:"},{"metadata":{"trusted":true},"id":"91797c03-d79d-446d-946a-1ecdd8184f44","cell_type":"code","source":"%%file signature.cpp\n\nint getMagnitude( int input ) {\n return input > 0 ? input : -input;\n}\n\ndouble getMagnitude( double input ) {\n return input > 0.0 ? input : -input;\n}\n\nint getMagnitude( short input ) {\n return input > 0 ? input : -input;\n}\n\nvoid demo( double dVal, float fVal, int* iPtr ){};","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"id":"07ca2086-0fc4-41df-8061-40aa13bc7f67","cell_type":"code","source":"!g++ -c signature.cpp","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"id":"773be3ed-09bb-48bc-9af6-75a6156db75c","cell_type":"code","source":"!nm -C signature.o","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"name":"xcpp17","display_name":"C++17","language":"C++17"},"language_info":{"codemirror_mode":"text/x-c++src","file_extension":".cpp","mimetype":"text/x-c++src","name":"c++","version":"17"}},"nbformat":4,"nbformat_minor":5} \ No newline at end of file