Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to c++ static virtual methods

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 } 
like image 364
raven Avatar asked Apr 27 '10 14:04

raven


People also ask

Can virtual method be static?

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.

Why static methods Cannot be virtual?

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.

Are there static methods in C?

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.

Can static method be virtual C#?

First of all, C# doesn't support virtual static method.


1 Answers

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."

like image 121
Rob Kennedy Avatar answered Oct 14 '22 03:10

Rob Kennedy