2011-10-13 123 views
1

以下是否會導致明確的行爲?也就是說,如果您將非可變參數函數f作爲可變參數函數g並使用f期望的參數調用g,那麼行爲是否與使用這些參數調用f的行爲相匹配?C++可變參數函數指針

class Base {}; 

class Derived1 : public Base { 
public: 
    int getInt1() {return 1;} 
}; 

class Derived2 : public Base { 
public: 
    int getInt2() {return 2;} 
}; 

typedef int (*vfunc)(...); 

int foo (vfunc f) { 
    Derived1 d1; 
    Derived2 d2; 
    return f(&d1, &d2); 
} 

int bar (Derived1 * p1, Derived2 * p2) { 
    return p1->getInt1() + p2->getInt2(); 
} 

int main (int argc, char ** argv) { 
    return foo((vfunc)bar); // Is this program guaranteed to return 3? 
} 

UPDATE

有一些辦法可以讓程序得到很好的界定,即使使用專有的關鍵字?比如做喜歡這裏提到的__cdecl一些東西:

http://msdn.microsoft.com/en-us/library/984x0h58%28v=vs.80%29.aspx

我的最終目標是擁有一個matcher功能,試圖X指針的列表匹配。匹配器函數接受一個謂詞(不一定是一個函數...可能是一個列表),並接受一個函數,它會將匹配的結果傳遞給它。傳遞給它的回調函數採用與謂詞匹配相同的參數類型和參數。

+0

我相信並期待答案是這是未定義的行爲。 –

+0

當你說「專有關鍵字」時,你是什麼意思?您定位的是什麼編譯器(以及版本和設置)?你打開其他更好的解決方案(如'std :: function')嗎? –

+0

像Visual Studio中的__cdecl一樣的東西。我也開放其他解決方案。 –

回答

6

否,該行爲是未定義,每C++ 11 5.2.11/6(reinterpret_cast):

通過一個指向函數類型調用函數的作用是不一樣的在函數的定義中使用的類型是未定義的。

bar的類型是int(Derived1*, Derived2*)。由f指向的函數的類型(通過其進行調用的表達式)是int(...)。兩者不一樣,因此行爲未定義。

+0

你能解釋一下這個例子中使用的函數的語言連接嗎? –

+0

@ K-ballo:道歉;複製和粘貼是我遇到麻煩的技巧。我已更正引用。 –

2

我很肯定答案是「不」。例如,在Visual C++中,可變參數函數將具有與正常函數不同的調用約定(當使用/Gz時)。

調用約定決定生成預調用和調用後彙編代碼,並且不能安全地混合這兩者。

+0

如果一個人將調用約定指定爲「cdecl」,那該怎麼辦? –

+0

@ K-ballo:你可能會很幸運,但它依賴於實現。我不相信C++中有任何規則說編譯器必須爲您提供一種自己指定調用約定的方法。實際上,C++標準對調用約定的含義很少。 (這意味着*假設最糟糕的:) – jwd