C ++访问类方法,通过类模板化函数中的指针

时间:2017-10-08 05:11:22

标签: c++ class templates methods function-pointers

我有一些不同类的对象,其中updaterendereventHandler方法对每个类都有相同的原型:

class Menu {
...
public:
    Menu ();

    void update (WindowState *winState);
    void render ();
    void eventHandler (SDL_Event *event);
};

class Game {
...
public:
    Game (Config *config);

    void update (WindowState *winState);
    void render ();
    void eventHandler (SDL_Event *event);
};

所以,我想“设置活动对象”并通过指针调用这些方法:

struct {
    void (*update) (WindowState *winState);
    void (*render) ();
    void (*eventHandler) (SDL_Event *event);
} routines;

template<class T>
void switchRoutines (T *obj) {
    routines.update = &(obj->update);
    routines.render = &(obj->render);
    routines.eventHandler = &(obj->eventHandler);
}
...
switchRoutines<Game> (&game);
...
routines.render ();

但是,我的类型不匹配:

error: cannot convert 'void (Game::*)(WindowState*)' to 'void (*)(WindowState*)' in assignment
    routines.update = &(obj->update);

我已经读过,应该在类中明确声明指向类成员的指针,但我的目标是编写一个通用的,与类无关的例程切换器。

有没有办法没有使用STL或Boost?

1 个答案:

答案 0 :(得分:0)

您可以使用类型擦除和模板功能来执行此操作,但必须还要保留对要调用成员函数的实例的引用。
这是一个最小的工作示例:

void *

您的期望已经存在,但是我添加了一个实例switchRoutines<Game> (&game); routines.render (routines.instance); 指针以使其正常工作:

routines

如果您可以将它添加到public class MainActivity extends AppCompatActivity { ListView listView; ArrayList<String> arrayList; ArrayAdapter<String> arrayAdapter; String infoText; int position; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Thread thread = new Thread(new Runnable(){ @Override public void run(){ SharedPreferences getPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); boolean isFirstStart = getPrefs.getBoolean("started",true); if(isFirstStart) { startActivity(new Intent (MainActivity.this,Intro.class)); SharedPreferences.Editor e = getPrefs.edit(); e.putBoolean("started", false); e.apply(); } } }); thread.start(); listView = (ListView) findViewById(R.id.ListView); arrayList = new ArrayList<>(); arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList); listView.setAdapter(arrayAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(); intent.setClass(MainActivity.this,EditMessageClass.class); intent.putExtra(Intent_Constants.INTENT_INFO_DATA,arrayList.get(position).toString()); intent.putExtra(Intent_Constants.INTENT_ITEM_POSITION,position); startActivityForResult(intent,Intent_Constants.INTENT_REQUEST_CODE_2); } }); } public void onClick(View v){ Intent intent = new Intent(); intent.setClass(MainActivity.this,EditFieldClass.class); startActivityForResult(intent,Intent_Constants.INTENT_REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (resultCode==Intent_Constants.INTENT_REQUEST_CODE){ infoText = data.getStringExtra(Intent_Constants.INTENT_INFO_FIELD); arrayList.add(infoText); arrayAdapter.notifyDataSetChanged(); } else if(resultCode==Intent_Constants.INTENT_REQUEST_CODE_2){ infoText = data.getStringExtra(Intent_Constants.INTENT_CHANGED_INFO); position = data.getIntExtra(Intent_Constants.INTENT_ITEM_POSITION,-1); arrayList.remove(position); arrayList.add(position,infoText); arrayAdapter.notifyDataSetChanged(); } } } 对象中,那么这里有一个可行的解决方案。