Установить функцию экземпляра класса после того, как она уже была определена - PullRequest
1 голос
/ 06 сентября 2010

Я пытаюсь дать классу функции событий, такие как .onShow () и .onHide (), поэтому при показе объекта будет работать функция .onShow (). Как можно разрешить изменение функции следующим образом:

MyClass myInst = MyClass();
myInst.onShow = OnShowFunction;

Возможно ли это разрешить?

Ответы [ 6 ]

6 голосов
/ 06 сентября 2010

Вы можете использовать функциональные указатели или std::function (также в BOOST) для достижения этой цели. Тем не менее, похоже, что вы, возможно, пытаетесь принять стиль программирования javascript или языка сценариев в C ++ - я бы предостерегал против этого, вам следует изменить свой стиль программирования в зависимости от того, как он соответствует языку. Типичная альтернатива в C ++ - иметь onShow виртуальный метод, который может быть переопределен производными.

3 голосов
/ 06 сентября 2010

Вы, вероятно, не хотите динамически менять функцию во время выполнения. Если вы это сделаете, один из других ответов покажет вам, как использовать функторы. Но для меня это звучит так, будто вы хотите, чтобы разные объекты имели разную функциональность в зависимости от некоторого свойства объекта.

Для чего предназначены виртуальные функции:

Вы определяете действие в базовом классе. Затем в производном классе вы предоставляете фактическую реализацию, основанную на том, как объект должен действовать.

class MyClass
{
    public:
        virtual void onShow() = 0;
};

class Window: public MyClass
{
    public:
        virtual void onShow() { /* Draw Window */ }
};

void aboutToShowObject(MyClass& obj)
{
    obj.onShow();
}
1 голос
/ 06 сентября 2010

Вот как вы это делаете (и одновременно поражаете и ужасаете своих коровников):

#include <iostream>

class MyClass
  {
public:
  void (MyClass::*OnShow)() ;
  void OnShowFunction() ;
  } ;

int main (int argc, char** argv)
  {
  MyClass C ;
  C.OnShow = MyClass::OnShowFunction ;
  (C.*C.OnShow)() ;
  }

void MyClass::OnShowFunction()
  {
  std::cout << "void MyClass::OnShowFunction()\n" ;
  }
1 голос
/ 06 сентября 2010

Да, это возможно.

Вам необходимо использовать указатель функции или оболочку, которая инкапсулирует указатели функций и другие вызываемые объекты, такие как function, которые можно найти в различных формах в C ++ 0x, C ++ TR1 и Boost .

В зависимости от того, как вы используете обратные вызовы, библиотека сигналов, такая как Boost.Signals , может быть более элегантной.

0 голосов
/ 06 сентября 2010

Если вы хотите динамически изменять указатель функции во время выполнения, вы можете оставить указатель функции в качестве члена и использовать метод по умолчанию OnShow (), который вызывает указатель функции:

#include <iostream>
using namespace std;

void OnShow() {
 cout << "Showing!" << endl;
}

typedef void(*EventProc)();

class Widget {
private:
 EventProc m_ep;
public:
 Widget() : m_ep(0) {}
 void SetOnShow(EventProc ep) {m_ep = ep;}
 void OnShow() {(*m_ep)();}
};

int main() {
 Widget w;
 w.SetOnShow(::OnShow);
 w.OnShow();
 return 0;
}
0 голосов
/ 06 сентября 2010

Вы можете использовать std :: function, которая является классом-оберткой, который позволит вам безопасно назначать функторы и функции C.
Однако использование иерархии функторов здесь является очень простым решением.

class Object  
{  
  BaseOnShow& onShow;  
}

class onShow1 : BaseOnShow { ... };
class onShow2 : BaseOnShow { ... };

...
Object obj;
onShow1 OnShowFunction;  // careful about the lifetime of this one
obj.onShow = OnShowFunction;

Затем, как обычно, определенные функции onShow должны использоваться через виртуальные члены-функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...