указатели — безопасно ли вызывать функцию-член, не определенную в базовом классе, из производного класса в c ++?

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

class base{
public:
typedef void (base::*methodPTR)();
methodPTR pfn;

void setMethod(methodPTR fn)
{
pfn = fn;
}
void run(){
if(pfn) (this->*pfn)();
}
};

class a : public base {
public:
};

class b : public base
{
a ob;
public:
void init()
{
//this function fn is not define neither in object "a" or "base"//but still I can assign arbitrary member function just like I wanted
ob.setMethod(static_cast<base::methodPTR>(&b::fn));
}

void fn()
{
cout << "from class b!" << endl;
}

void test()
{
ob.run();
}
};

int _tmain(int argc, _TCHAR* argv[])
{
b x;
x.init();
x.test();

return 0;
}

2

Решение

Делать то, что вы делаете, безопасно, если вы уверены, что никогда не вызовете указатель члена на объект, который на самом деле не относится к одному из типов, из которых поступил указатель (то есть вы не вызываете a::x на base).

0

Другие решения

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

   //store objects vs callbacks
//you could replace int in map with some condition or key to invoke a callback
#include <iostream>
#include <map>

using namespace std;

template<class T>
class A {
protected:
void (T::*curr_f)();
private:
static std::map<int, std::map<T*,void (T::*)() > > callBacks;
public:

virtual void set(void (T::*f)()) {
curr_f = f;
cout<<"Set in A"<<endl;
T* obj = new T();
static int x = 0;
callBacks[++x][obj] = f;
//      (obj->*curr_f)();
}

virtual void new_function() {cout<<"in A"<<endl;};

static void run()
{
for(typename std::map<int,std::map<T*,void (T::*)() > >::iterator itr = A<T>::callBacks.begin();
itr != A<T>::callBacks.end(); ++itr)
{
for(typename std::map<T*,void (T::*)() >::iterator itr2 = itr->second.begin();
itr2 != itr->second.end(); ++itr2)
{
((itr2->first)->*(itr2->second))();
}
}
}

};

template<class T>
std::map<int, std::map<T*,void (T::*)() > > A<T>::callBacks;

class B :public A<B> {

public:
void func() {
set(&B::new_function);
};
void new_function() {cout<<"in B"<<endl;};

};

class C:public A<C> {

public:
void func() {
set(&C::new_function);
};
void new_function() {cout<<"in C"<<endl;};

};

int main()
{

B obj1;
C obj2;
obj1.func();
obj2.func();
A<B>::run();
A<C>::run();
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector