0

I want to create a static function pointer array, so I can jump to a certain function regarding a received index. Like an index jumper.

So imagine a class like this:

Class A 
{ 
  private:
  static void 1stFunction();
  static void 2ndFunction();

  static void(*functionPointer[20])(void);

};

Then I would like that functionPointer to get the value of the 1stFunction and 2ndFunction, and maybe even more. So, how do I initialize it? As far as I know, when a static member is declared, you can use it even before an instance is created. So I though, lets initialize that function pointer, so later I can call it like this

functionPointer[receivedIndex]();

So i tried to initilize it like this, in the same .h file

void (*A::functionPointer[])(void) =
{
    A::1stFunction,
    A::2ndFunction,
};

But the compiler gives me redifinition, it says it's already created.

So, pretty sure I'm missing something. I don't know though, if it is syntax or simply it is not possible to do it this way. I know that function pointers to class's member functions are different than normal function pointers... But this is a static function, so I believe it doesn't belong to an instance and therefore it should work with normal function pointers.

Any help would be appreciated. Thanks

Wer Bn
  • 173
  • 1
  • 10

2 Answers2

4

The following would be a working example that probably achieves what you need.

You need C++11 for the initializer list.

It is a good practice to initialize the static member in the cpp file, as you don't want to have a definition of the static member everytime the header is included (this can lead to linking issues).

You can call callf with the desired index and have the corresponding function called, based on the initialization of the function pointer array.

The output of the program would be:

I am 2ndFunction

Header file

class A
{
private:
  static void Function1();
  static void Function2();

  static void(*functionPointer[20])();

public:
  static void callf(int index);
};

Implementation

#include <iostream>
#include "ex.h"

void(*A::functionPointer[20])() {
  A::Function1,
  A::Function2
};

void A::Function1() {
  std::cout << "I am 1stFunction" << std::endl;
}

void A::Function2() {
  std::cout << "I am 2ndFunction" << std::endl;
}

void A::callf(int index) {
  A::functionPointer[index]();
}

int main(int argc, char const *argv[]) {
  A::callf(1);
  return 0;
}
Vincenzo Pii
  • 18,961
  • 8
  • 39
  • 49
  • Thank you for your answer. But it gives me unresolved external symbol for A::Function1 and A::Function2 – Wer Bn Aug 12 '15 at 08:09
  • @WerBn make sure you link all of your object files together. – Quentin Aug 12 '15 at 08:16
  • @WerBn you need to link the object file where you *define* those functions, – Vincenzo Pii Aug 12 '15 at 08:18
  • Ya :P Good point, I forgot to define the functions. Thank you very much. I almost got it. Real problem was the definition of the array in the .h file. Thank you! – Wer Bn Aug 12 '15 at 08:34
  • Btw, do you know a way of initializing dinamically this array? Just imagine it's not a static array pointing for non-static member functions. Can you also list-initialize it? I«m trying, but I can't – Wer Bn Aug 13 '15 at 12:46
  • @WerBn, maybe you can make a mvce and post a new question for that, not comfortable to use comments :) – Vincenzo Pii Aug 13 '15 at 13:53
3

Here you have a more modern C++ approach (C++14 needed) I would advise you to explore lambda functions if you are not restricted to C++03.

#include <iostream>
#include <functional>
#include <vector>

class A {
public:

  using f_type = std::function<void(void)>;
  f_type f1 = []() { std::cout << "f0" << std::endl;};
  f_type f2 = []() { std::cout << "f1" << std::endl;};
  static void f3() { std::cout << "f3" << std::endl; }

  std::vector<f_type> functions{f1, f2, f3};

};


int main() {

  A a;
  a.functions[0]();
  a.functions[1]();
  //adding custom lambda
  a.functions.emplace_back([](){ std::cout << "custom f" << std::endl;});
  a.functions[2]();

  return 0;
}

you can add both functions and lambdas to your container.

dau_sama
  • 4,247
  • 2
  • 23
  • 30
  • 1
    Using `std::function` here is incredibly overkill. – Quentin Aug 12 '15 at 08:16
  • it is more readable and it will allow him to easily use stl algorithms on his function pointer containers. Unless you're in an environment where nanoseconds matter, I wouldn't go down the function pointer route. I will never understand why people are so reluctant to new modern ways of coding. – dau_sama Aug 12 '15 at 08:28
  • `using f_type = void (*)(void)` can't really be said to hurt readability in my opinion, and std algorithms work perfectly well with function pointers. `std::function` is not a "modern function pointer" (whatever that coud mean), it's a type-erased functionoid container. – Quentin Aug 12 '15 at 08:35
  • Why std::vector ? Is is static this way? I would like to stick to old faction and use function pointer without a template. But thank you anyway :) – Wer Bn Aug 12 '15 at 08:35
  • feel free to change it to std::array. – dau_sama Aug 12 '15 at 10:07
  • @Quentin, if at runtime you want to move a lambda function into a container, it is more modern and readable. Also, having them in a stl container instead of an array, helps syntax if you need to pass them around as references. If the code would be tagged as C code, I would agree, but this is C++ – dau_sama Aug 12 '15 at 10:13
  • @dau_sama replacing the C array is definitely a good idea, but replacing a plain static function and its pointer by a `std::function` containing a lambda is completely gratuitous. It is not more legible, it does not need to be that flexible, and it actively hurts performance for no reason. – Quentin Aug 12 '15 at 11:32
  • @Quentin, until you actually need that flexibility, and you have already too much code that it will be impossible to upgrade. One could argue that C++ itself is overkill for such a task, you could do it perfectly in C. And even then one could argue that in assembly it would be better. Difference of opinions I guess. – dau_sama Aug 12 '15 at 12:35
  • @dau_sama the upgrade is one typedef away. And there's no question of choosing a language here, it's about not using the heaviest and all-powerful tool to perform the most basic task just because the tool is shiny. – Quentin Aug 12 '15 at 12:45
  • let's all use "char* " and raw pointers because strings and smart pointers are so shiny! – dau_sama Aug 12 '15 at 12:53