2013-08-21 33 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