2011-05-16 99 views
4

我正在編寫一個內存測試框架,在該框架中,我用自己的(例如malloc,realloc,free等)替換了動態內存分配函數。但是,系統需要靜態功能(我無法改變這一點)。將成員函數轉換爲C++中的靜態函數

我有一個MemoryTester類,它記錄內存調用,並且我想綁定它的內存分配函數的成員函數實現。這可能與C++?

編輯:

下面是一些代碼高亮我想要做的事:

typedef void*(allocateFuncPtr) (uint8_t); 
typedef void (freeFuncPtr) (void*); 

void setAllocateFunction(allocateFuncPtr) {...} 
void setFreeFunction(freeFuncPtr) {...} 


class MemoryTester 
{ 
    void *malloc(uint8_t size); 
    void free(void *ptr); 
} 

int main() 
{ 
    MemoryTester *tester = new MemoryTester(); 

    //want to set allocate and free functions to those in tester 
    setAllocateFunction(tester->getAllocateFunction()); 
    setFreeFunction(tester->getFreeFunction()); 

    return 0; 
} 
+0

您是否有特定的對象在綁定時調用這些成員函數? – fredoverflow 2011-05-16 20:35:54

+0

我看不到你的currend代碼,你需要函數指針嗎?如果不看看std :: bind。 – Fox32 2011-05-16 20:36:03

回答

3

編輯後,意圖似乎更清楚我。最簡單的方法是使用MemoryTester中的靜態成員函數,而不是非靜態成員函數。如果他們需要保持狀態,那麼該狀態將不得不移動到該班級的成員static

+0

這就是我現在正在做的,但我想知道是否有更好的方法。我想C++在這種方式中不夠靈活。 – 2011-05-16 21:32:18

+0

這與靈活性無關,非靜態成員函數具有隱藏的'this'參數,並且使簽名不相容。如果允許您只將指針傳遞給成員函數,其狀態將被修改,那麼隱含的'this'參數將指向哪個對象? – 2011-05-16 21:38:29

+0

在其他語言(例如JavaScript)中,您可以在運行時動態創建一個函數,因此您可以爲每個初始化的對象創建一組新的函數。在其他語言中,仍然可以將對象指針粘貼到函數中。我只是想知道C++是否有類似的東西。 – 2011-05-16 21:43:56

-2

有一個單MemoryTester對象,並且有靜態橋函數調用該對象的成員函數。

+2

我倒下了這個。 OP可能會喜歡使用全局對象,但我絕對不需要強制該對象是唯一的。 – Puppy 2011-05-16 20:39:56

+2

[不要使用單身人士](http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/) – jalf 2011-05-17 06:25:12

+2

現在,我知道單身人士是所有可能情況下的禁忌詞,我希望我也可以在答案中加入goto。 – Dialecticus 2011-05-17 10:04:36

0

如果我正確理解你所問的,沒有「綁定」。一旦分配了內存,你可以告訴編譯器它是通過用戶類型轉換的,在你的情況下是reinterpret_cast。例如,在你配置函數中:

unsigned char* raw_memory = allocation(std::size_t); 
MyFinalType* object = reinterpret_cast<MyFinalType*>(raw_memory); // tells the compiler to take this memory as a MyFinalType. 

然後你返回你的最終類型。

要知道使用哪種類型,您一定要使用模板。

不要忘記C++是一種靜態類型語言:你不能將函數綁定到對象類型。好吧,你可以,但是,你必須使用std :: function或函數指針,這不是你想要的。

0

除非你創建一個全局對象,否則不是。如果框架需要定期的函數指針,那麼你就會被它所提供的東西所困擾,如果它沒有提供傳統的void * userdata風格,那麼你會被塞滿,或者它是全局對象時間。

1

如果您使用的是GCC,那麼您可以讓鏈接器使用--wrap選項(或-Wl, - wrap,malloc)來包裝函數。

然後,您可以攔截對malloc的調用,因爲對該函數的所有調用都將重定向到__wrap_malloc。你可以使用__real_malloc這個名字來調用真正的(原始的c-lib)malloc函數,或者你可以用你自己的替換來代替(如果__real_malloc沒有被調用,那麼鏈接器可能會死掉原來的c- lib malloc全能)。

void *__wrap_malloc (size_t c) 
{ 
    printf ("malloc called with %zu\n", c); 
    return __real_malloc (c); 
} 

FWIW,可以更換新的全球和刪除操作,然後你可以只使用自己的存儲系統(甚至當你從第三方編譯庫,只要使用代碼,因爲他們沒有超載有一個程序全局新建和刪除)。

下面是一些偉大的信息:Tutorial of Replacing "new" and "delete"

+1

這根本不回答這個問題,因爲它們不是成員函數。 – Puppy 2011-05-16 21:06:27

+0

這個問題很不明確,因爲他說他想重寫內存函數(malloc等)。你說他想用成員函數來做。我不太確定他聲稱這些函數必須是「靜態的」,因爲他的成員函數沒有被定義爲「靜態」。無論如何...猜猜這只是一個糟糕的措辭選擇,因爲問題沒有定義,所有的答案都不會是正確的。 – Adisak 2011-05-16 21:15:42

+0

他在他的問題中說,他不能改變他的系統採用免費函數指針。問題是明確的 - 他有一個框架,要免費函數指針,他想使用成員函數 – Puppy 2011-05-16 21:16:30

3

如果你的編譯器支持0X lambda表達式,你可以使用閉包:

int main() { 
    MemoryTester tester; // If no need for dynamic allocation, don't use it. 

    setAllocateFunction([&tester](uint8_t size) { return tester.malloc(size); }); 
    setFreeFunction([&tester](void *p) { tester.free(p); }); 

    return 0; 
} 

需要您MemoryTester類也不是哪個庫setAllocateFunction & setFreeFunction不屬於任何變化。


沒有lambda表達式,而不是a singleton class,使用一個全局對象:

struct MemoryTester { 
    void* malloc(uint8_t size); // Neither are static. 
    void free(void *p); 
}; 

MemoryTester tester_a; 
void* tester_a_malloc(uint8_t size) { return tester_a.malloc(size); } 
void tester_a_free(void *p) { return tester_a.free(p); } 

int main() { 
    setAllocateFunction(&tester_a_malloc); 
    setFreeFunction(&tester_a_free); 
} 

這樣做的優點是整個MemoryTester類,因爲它一個特別需要不陷於癱瘓。您可以根據需要創建更多功能(例如tester_b_malloc/free),以適應同一程序中的其他用途。