In C++ is not possible to declare a static virtual function, neither cast a non-static function to a C style function pointer.
Now, I have a plain ol' C SDK that uses function pointers heavily.
I have to fill a structure with several function pointers. I was planning to use an abstract class with a bunch of static pure virtual methods, and redefine them in derived classes and fill the structure with them. It wasn't until then that I realized that static virtual are not allowed in C++.
Also this C SDKs function signature doesn't have a userData param.
Is there any good alternative? The best I can think of is defining some pure virtual methods GetFuncA(), GetFuncB(),... and some static members FuncA()/FuncB() in each derived class, which would be returned by the GetFuncX(). Then a function in the abstract class would call those functions to get the pointers and fill the structure.
Edit Answering to John Dibling, it would be great to be able to do this:
class Base { FillPointers() { myStruct.funA = myFunA; myStruct.funB = myFunB; ...} private: CStruct myStruct; static virtual myFunA(...) = 0; static virtual myFunB(...) = 0; }; class Derived1 : public Base { Derived1() { FillPointers(); } static virtual myFunA(...) {...}; static virtual myFunB(...) {...}; }; class Derived2 : public Base { Derived2() { FillPointers(); } static virtual myFunA(...) {...}; static virtual myFunB(...) {...}; }; int main() { Derived1 d1; Derived2 d2; // Now I have two objects with different functionality }
A virtual function cannot be global or static because, by definition, a virtual function is a member function of a base class and relies on a specific object to determine which implementation of the function is called.
Can Static Functions Be Virtual in C++? In C++, a static member function of a class cannot be virtual. Virtual functions are invoked when you have a pointer or reference to an instance of a class. Static functions aren't tied to the instance of a class but they are tied to the class.
A static function in C is a function that has a scope that is limited to its object file. This means that the static function is only visible in its object file. A function can be declared as static function by placing the static keyword before the function name.
First of all, C# doesn't support virtual static method.
You can make Base
be a class template that takes its function pointers from its template argument:
extern "C" { struct CStruct { void (*funA)(int, char const*); int (*funB)(void); }; } template <typename T> class Base { public: CStruct myStruct; void FillPointers() { myStruct.funA = &T::myFunA; myStruct.funB = &T::myFunB; } Base() { FillPointers(); } };
Then, define your derived classes to descend from an instantiation of Base
using each derived class as the template argument:
class Derived1: public Base<Derived1> { public: static void myFunA(int, char const*) { } static int myFunB() { return 0; } }; class Derived2: public Base<Derived2> { public: static void myFunA(int, char const*) { } static int myFunB() { return 1; } }; int main() { Derived1 d1; d1.myStruct.funA(0, 0); d1.myStruct.funB(); Derived2 d2; d2.myStruct.funA(0, 0); d2.myStruct.funB(); }
That technique is known as the curiously recurring template pattern. If you neglect to implement one of the functions in a derived class, or if you change the function signature, you'll get a compilation error, which is exactly what you'd expect to get if you neglected to implement one of the pure virtual functions from your original plan.
The consequence of this technique, however, is that Derived1
and Derived2
do not have a common base class. The two instantiations of Base<>
are not related in any way, as far as the type system is concerned. If you need them to be related, then you can introduce another class to serve as the base for the template, and then put the common things there:
class RealBase { public: CStruct myStruct; }; template <typename T> class Base: public RealBase { // ... }; int main() RealBase* b; Derived1 d1; b = &d1; b->myStruct.funA(0, 0); b->myStruct.funB(); Derived2 d2; b = &d2; b->myStruct.funA(0, 0); b->myStruct.funB(); }
Beware: Static member functions are not necessarily compatible with ordinary function pointers. In my experience, if the compiler accepts the assignment statements shown above, then you can at least be confident that they're compatible for that compiler. This code isn't portable, but if it works on all the platforms you need to support, then you might consider it "portable enough."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With