2010-02-23 97 views
2

如果存在多種可能性,C++編譯器如何決定調用哪個函數/方法? 以我特定情況下,我有的C++運行時間的標準自由功能和我也有一個模板自由變型中,是這樣的:在C++中解析函數/方法/模板名稱的首選項是什麼?

// The definitions of the C++ Run Time Library (from memory.h) 
extern malloc(size_t s); 
extern void free(void *p); 

// Our own memory management functions 
extern void *OurMalloc(size_t s); 
extern void OurFree(void *p); 

// Own variants to overrule malloc and free (instead of using #define) 
template<typename T> 
void *malloc(T t) 
{ 
return OurMalloc(t); 
} 

template<typename T> 
void free(T *t) 
{ 
OurFree(t); 
} 

我測試此使用以下代碼:

void main(void) 
{ 
void *p = malloc(10); 
free(p); 
} 

如果我編譯並運行它,看起來對malloc的調用被模板變體正確地替換了。到現在爲止還挺好。

但是,免費的調用不會被替換爲模板變體,並且標準C++函數仍然被調用。

C++編譯器使用哪些規則來決定哪個變體優先? 這與Koenig查找規則有關嗎?

注意:我試過這種方法,因爲使用#define不能解決問題(請參閱問題How to use C macro's (#define) to alter calls but not prototypes)。

+2

這是C問題還是C++問題?如果你使用模板,它必須是C++。但它被標記爲C,並且您正在使用malloc()。咦? – 2010-02-23 16:21:48

+0

@Fred Larson:我已經將問題編輯爲純C++ - 提問者可能感到困惑,因爲MSVC似乎混淆了C和C++。 – 2010-02-23 16:24:33

+1

對。我其實正在試圖解決一個C malloc/free問題。因此我最初使用c標籤。但是你是對的,它必須是C++。 – Patrick 2010-02-23 16:24:44

回答

8

重載分辨率一般來說相當複雜。

就你而言,這很簡單:如果有完全匹配,則不考慮函數模板。免費的情況下(標準免費採取void *),對於malloc它不是(標準的malloc需要size_t,你傳遞一個int並且size_t不能是一個typedef int - size_t是無符號的)。如果您使用void *以外的類型進行免費調用,則應該實例化您的模板。

運行:

#include <iostream> 

void* ml(size_t s) 
{ 
    std::cout << "ml(size_t)\n"; 
} 

void fr(void *p) 
{ 
    std::cout << "fr(void*)\n"; 
} 

template<typename T> 
void* ml(T t) 
{ 
    std::cout << "ml<" << typeid(T).name() << ">(T)\n"; 
} 

template<typename T> 
void fr(T *t) 
{ 
    std::cout << "fr<" << typeid(T).name() << ">(T*)\n"; 
} 

int main() 
{ 
    void* p1 = ml((size_t)10); 
    fr(p1); 
    int* p2 = (int*)ml(10); 
    fr(p2); 
    return 0; 
} 

我得到

ml(size_t) 
fr(void*) 
ml<i>(T) 
fr<i>(T*) 

和我是什麼返回typeid(int).name()

+0

感謝您的解釋,儘管我希望能有一個答案讓我可以輕鬆地覆蓋malloc和free。 – Patrick 2010-02-23 16:50:18

+0

我不確定你想要達到什麼目的。如果你想使用你自己的malloc/free實現,這通常由標準庫實現支持,並且可以在鏈接時實現。但是你必須檢查你的實現以獲取關於它的信息。 – AProgrammer 2010-02-23 16:58:09

3

你對mallocfree特定問題,問題是,在您的來電malloc

void *p = malloc(10); 

將參數10鍵入爲int,而運行時的malloc()的簽名要求參數unsigned。由於沒有完全匹配,編譯器更喜歡模板化的malloc,它可以創建完全匹配。

當你撥打:

free(p); 

p類型是void*這不正是運行時的簽名free()匹配,因此編譯器不會理會使用模板free

2

使用這種技術不可能「替換」標準malloc。其他答案已經解釋過,因爲您使用已簽名的值作爲malloc調用中的一個參數,所以您的模板版本恰好「勝過」標準版本,因爲標準版本需要未簽名參數。

爲了更好地說明這一點,我只是想補充一點,如果你在你的malloc通話

void *p1 = malloc(10u); 
void *p2 = malloc(10ul); 

提供任何的unsigned intunsigned long參數,你會發現,在這些調用你的malloc模板版本之一也不再「工作」,並且標準調用被稱爲相反,因爲它與參數更匹配(前提是您的平臺被定義爲unsigned intunsigned long

+0

Andrey,這取決於size_t是無符號的。在這裏,size_t是無符號的長整型,所以你需要10ul來獲得匹配 - 這就是爲什麼我在我的答案中轉而使用size_t而不是使用後綴。 – AProgrammer 2010-02-23 16:49:14

+0

@AProgrammer:你說得對。我會更新我的答案。 – AnT 2010-02-23 19:16:34

0

沒有回答你問的問題,但看起來你正在嘗試做的事情:

如果它在你的系統上可用,你可以使用LD_PRELOAD來預裝一個你構建的.so庫,它有你的malloc版本和自由。那麼他們肯定會被調用而不是標準版本。

相關問題