main.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Member Function Pointers and the Fastest Possible C++ Delegates.cpp : This file contains the 'main' function. Program execution begins and ends there.
  2. // https://www.codeproject.com/KB/cpp/FastDelegate.aspx
  3. /*
  4. */
  5. #include <iostream>
  6. #include <stdio.h>
  7. #include "FastDelegate.h"
  8. // Demonstrate the syntax for FastDelegates.
  9. // -Don Clugston, May 2004.
  10. // It's a really boring example, but it shows the most important cases.
  11. // Declare some functions of varying complexity...
  12. void SimpleStaticFunction(int num, char* str) {
  13. printf("In SimpleStaticFunction. Num=%d, str = %s\n", num, str);
  14. }
  15. void SimpleVoidFunction() {
  16. printf("In SimpleVoidFunction with no parameters.\n");
  17. }
  18. class CBaseClass {
  19. protected:
  20. char* m_name;
  21. public:
  22. CBaseClass(char* name) : m_name(name) {};
  23. void SimpleMemberFunction(int num, char* str) {
  24. printf("In SimpleMemberFunction in %s. Num=%d, str = %s\n", m_name, num, str);
  25. }
  26. int SimpleMemberFunctionReturnsInt(int num, char* str) {
  27. printf("In SimpleMemberFunction in %s. Num=%d, str = %s Return: -1\n", m_name, num, str); return -2;
  28. }
  29. void ConstMemberFunction(int num, char* str) const {
  30. printf("In ConstMemberFunction in %s. Num=%d, str = %s\n", m_name, num, str);
  31. }
  32. virtual void SimpleVirtualFunction(int num, char* str) {
  33. printf("In SimpleVirtualFunction in %s. Num=%d, str = %s\n", m_name, num, str);
  34. }
  35. static void StaticMemberFunction(int num, char* str) {
  36. printf("In StaticMemberFunction. Num=%d, str =%s\n", num, str);
  37. }
  38. };
  39. class COtherClass {
  40. double rubbish = 12; // to ensure this class has non-zero size.
  41. public:
  42. virtual void UnusedVirtualFunction(void) {}
  43. virtual void TrickyVirtualFunction(int num, char* str) = 0;
  44. };
  45. class VeryBigClass {
  46. int letsMakeThingsComplicated[400];
  47. };
  48. // This declaration ensures that we get a convoluted class heirarchy.
  49. class CDerivedClass : public VeryBigClass, virtual public COtherClass, virtual public CBaseClass
  50. {
  51. double m_somemember[8];
  52. public:
  53. CDerivedClass() : CBaseClass((char*)"Base of Derived") { m_somemember[0] = 1.2345; }
  54. void SimpleDerivedFunction(int num, char* str) { printf("In SimpleDerived. num=%d\n", num); }
  55. virtual void AnotherUnusedVirtualFunction(int num, char* str) {}
  56. virtual void TrickyVirtualFunction(int num, char* str) {
  57. printf("In Derived TrickyMemberFunction. Num=%d, str = %s\n", num, str);
  58. }
  59. };
  60. using namespace fastdelegate;
  61. int main(void)
  62. {
  63. // Delegates with up to 8 parameters are supported.
  64. // Here's the case for a void function.
  65. // We declare a delegate and attach it to SimpleVoidFunction()
  66. printf("-- FastDelegate demo --\nA no-parameter delegate is declared using FastDelegate0\n\n");
  67. FastDelegate0<> noparameterdelegate(&SimpleVoidFunction);
  68. noparameterdelegate(); // invoke the delegate - this calls SimpleVoidFunction()
  69. printf("\n-- Examples using two-parameter delegates (int, char *) --\n\n");
  70. // By default, the return value is void.
  71. typedef FastDelegate2<int, char*> MyDelegate;
  72. // If you want to have a non-void return value, put it at the end.
  73. typedef FastDelegate2<int, char*, int> IntMyDelegate;
  74. MyDelegate funclist[12]; // delegates are initialized to empty
  75. CBaseClass a((char*)"Base A");
  76. CBaseClass b((char*)"Base B");
  77. CDerivedClass d;
  78. CDerivedClass c;
  79. IntMyDelegate newdeleg;
  80. newdeleg = MakeDelegate(&a, &CBaseClass::SimpleMemberFunctionReturnsInt);
  81. printf("Return value: %d\n", newdeleg(0, (char*)"return value"));
  82. // Binding a simple member function
  83. funclist[0].bind(&a, &CBaseClass::SimpleMemberFunction);
  84. // You can also bind static (free) functions
  85. funclist[1].bind(&SimpleStaticFunction);
  86. // and static member functions
  87. funclist[2].bind(&CBaseClass::StaticMemberFunction);
  88. // and const member functions (these only need a const class pointer).
  89. funclist[11].bind((const CBaseClass*)&a, &CBaseClass::ConstMemberFunction);
  90. funclist[3].bind(&a, &CBaseClass::ConstMemberFunction);
  91. // and virtual member functions
  92. funclist[4].bind(&b, &CBaseClass::SimpleVirtualFunction);
  93. // You can also use the = operator. For static functions, a fastdelegate
  94. // looks identical to a simple function pointer.
  95. funclist[5] = &CBaseClass::StaticMemberFunction;
  96. // The weird rule about the class of derived member function pointers is avoided.
  97. // For MSVC, you can use &CDerivedClass::SimpleVirtualFunction here, but DMC will complain.
  98. // Note that as well as .bind(), you can also use the MakeDelegate()
  99. // global function.
  100. funclist[6] = MakeDelegate(&d, &CBaseClass::SimpleVirtualFunction);
  101. // The worst case is an abstract virtual function of a virtually-derived class
  102. // with at least one non-virtual base class. This is a VERY obscure situation,
  103. // which you're unlikely to encounter in the real world.
  104. // FastDelegate versions prior to 1.3 had problems with this case on VC6.
  105. // Now, it works without problems on all compilers.
  106. funclist[7].bind(&c, &CDerivedClass::TrickyVirtualFunction);
  107. // BUT... in such cases you should be using the base class as an
  108. // interface, anyway.
  109. funclist[8].bind(&c, &COtherClass::TrickyVirtualFunction);
  110. // Calling a function that was first declared in the derived class is straightforward
  111. funclist[9] = MakeDelegate(&c, &CDerivedClass::SimpleDerivedFunction);
  112. // You can also bind directly using the constructor
  113. MyDelegate dg(&b, &CBaseClass::SimpleVirtualFunction);
  114. char* msg = (char*)"Looking for equal delegate";
  115. for (int i = 0; i < 12; i++) {
  116. printf("%d :", i);
  117. // The == and != operators are provided
  118. // Note that they work even for inline functions.
  119. if (funclist[i] == dg) { msg = (char*)"Found equal delegate"; };
  120. // operator ! can be used to test for an empty delegate
  121. // You can also use the .empty() member function.
  122. if (!funclist[i]) {
  123. printf("Delegate is empty\n");
  124. }
  125. else {
  126. // Invocation generates optimal assembly code.
  127. funclist[i](i, msg);
  128. };
  129. }
  130. return 0;
  131. }
  132. /*
  133. -- FastDelegate demo --
  134. A no-parameter delegate is declared using FastDelegate0
  135. In SimpleVoidFunction with no parameters.
  136. -- Examples using two-parameter delegates (int, char *) --
  137. In SimpleMemberFunction in Base A. Num=0, str = return value Return: -1
  138. Return value: -2
  139. 0 :In SimpleMemberFunction in Base A. Num=0, str = Looking for equal delegate
  140. 1 :In SimpleStaticFunction. Num=1, str = Looking for equal delegate
  141. 2 :In StaticMemberFunction. Num=2, str =Looking for equal delegate
  142. 3 :In ConstMemberFunction in Base A. Num=3, str = Looking for equal delegate
  143. 4 :In SimpleVirtualFunction in Base B. Num=4, str = Found equal delegate
  144. 5 :In StaticMemberFunction. Num=5, str =Found equal delegate
  145. 6 :In SimpleVirtualFunction in Base of Derived. Num=6, str = Found equal delegate
  146. 7 :In Derived TrickyMemberFunction. Num=7, str = Found equal delegate
  147. 8 :In Derived TrickyMemberFunction. Num=8, str = Found equal delegate
  148. 9 :In SimpleDerived. num=9
  149. 10 :Delegate is empty
  150. 11 :In ConstMemberFunction in Base A. Num=11, str = Found equal delegate
  151. */