2013-08-21 31 views
3

短版本:如何在运行时更改方法的行为?

重点是一个实例的(复杂)状态可以被该类的定义之外的函数改变,因为这样的类可以被扩展为具有各种内部状态而不会污染许多国家制定者的阶级定义。

假设下面的代码:

class bar 
{ 
     virtual void ChangeState()=0; 
} 
class foo:bar 
{ 
private: 
     int b; 
public: 
     void ChangeState() {b=3;} 
} 

我想要做的是创造不同的功能,然后将它们传递给函数,在运行时,像

foo.ChangeState(); //b is 3 now 
void foo::(?)ChangeState2(){ b=2; }; 
foo.ChangeState=ChangeState2; 
foo.ChangeState(); //b is 2 now 

可不可以这样的构建用C++实现,而不使用黑客?

+0

没有办法,你可以[语言的定义在运行时更改C中的函数++,显然,如果你可以在内存中找到正确的地址,并使内存可写,你可以写入新的指令到内存]。 –

+0

@MatsPetersson:你可以改变一个函数_pointer_ –

+0

@Minging Duck:显然,是的。这是一种选择。 –

回答

2

也许,这将帮助:

#include <iostream> 

namespace so 
{ 

class B 
{ 
    friend void change_1(B *); 
    friend void change_2(B *); 
    friend void change_3(B *); 

    int i; 
public: 
    B() : i{ 0 } {} 

    void change_state(void (*_function)(B *)) 
    { 
    _function(this); 

    std::cout << i << std::endl; 
    } 
}; 

void change_1(B * _object) 
{ 
_object->i = -1; 
} 
void change_2(B * _object) 
{ 
_object->i = -2; 
} 
void change_3(B * _object) 
{ 
_object->i = -3; 
} 

} //namespace so 

int main() 
{ 
so::B b{ }; 

b.change_state(so::change_1); 
b.change_state(so::change_2); 
b.change_state(so::change_3); 

return(0); 
} 
+2

这是[类似于我想出的](http://coliru.stacked-crooked.com/view?id=2374eff4521ef575b7c21854a02662a0-c96156d6cc95286981b0e9deef2eefae) –

+1

@MooingDuck +1我会说这两种方式基本上是一样的。事实上,使'静态'函数更加符合逻辑。但我不得不说,我认为OP在问一个错误的问题。我想,他应该问“对于有很多数据成员需要'设置/获取'的班级来说,一个平滑的设计是什么?”。 – lapk

+0

@PetrBudnik你是对的,也许我应该发表另一个问题。 – Taikand

2

简答:这是不可能的。

你可以做的是定义多个类,并根据一些运行时条件在它们之间进行选择。当然,该对象并不一定是完整的类,我们可以做这样的事情:

class foo: public bar 
{ 
    private: 
     class ChangeState 
     { 
     public: 
      virtual void DoChangeState(foo *f) = 0; 
     }; 
     class ChangeState2 
     { 
     public: 
      virtual void DoChangeState(foo *f) { f->b = 2 } ; 
     }; 
     class ChangeState3 : public ChangeState 
     { 
     public: 
      virtual void DoChangeState(foo *f) { f->b = 3 } ; 
     }; 
    ChangeState *stateChanger 

    public: 
     foo() { stateChanger = new ChangeState3; } 
     void SetStateChange2() { delete stateChanger; stateChanger = new ChangeState2; } 
     ~foo() { delete stateChanger; } 
     void ChangeState() { stateChanger->DoChangeState(this); } 
}; 

我敢肯定有关于这一主题的其他变化(和你应该使用智能指针)。

1

使用您所描述的语法,你不能改变在运行时的行为。但是,如果你希望通过使用函数指针获得类似的东西,你可以。

但是,如果我理解你想正确完成什么,我想看看执行strategy pattern