所以我有一個變體類,我最近添加了存儲指向成員函數數據的功能。它使用下面的代碼來實現它。成員函數指針的解決方法是一個壞的破解?
class Variant
{
void* _value;
template <typename T1>
void Variant::ThisCall(T1* pThis)
{
typedef void(T1::* fptr)();
fptr a;
int* iiVal = new (&a) int;
*iiVal = *((int*)_value);
(pThis->*a)();
}
};
// usage
Variant myfunc = &SomeClass::SomeMethod;
SomeClass* s = new SomeClass();
myfunc.ThisCall(s);
我爲這個解決方案工作的最大的事情是指針到成員函數不能轉換爲void *。所以賦值運算符的種類基本上完成了這個操作的逆過程。它獲取給定的數據,將其作爲一個int指針(如果它是一個指針本身)並將int指針賦給void *,這是完全合法的。
所以我的問題是這樣的:爲什麼我覺得這是一個可怕的解決方案?我覺得這是一個很大的破解,它必須有一些嚴重的問題,但是我已經在這個問題上如此深刻了幾天,現在我看不到它過去了。謝謝!
[EDIT#1]
一位評論者指出,這可能不與虛擬方法的工作。我已經使用下面的代碼進行了測試,它似乎檢查出來。
class ImplA : public Base
{
public:
virtual void Print()
{
cout << "ImplA print\n";
}
};
class ImplB : public Base
{
public:
virtual void Print()
{
cout << "ImplB print\n";
}
};
class ImplC : public ImplA
{
public:
virtual void Print()
{
cout << "ImplC print\n";
}
};
// usage
Variant x = &Base::Print;
auto b = new ImplA; // replace ImplA with ImplB or ImplC and it works as expected
x.ThisCall(b);
對於一些額外的信息,我使用VS2010作爲我的編譯器。謝謝!
[編輯#2]
來提供內容,我一直在這個變體類很短的一段時間,現在,我試圖使它支持任何你能在它扔。在這樣做的時候,我想到了函數指針和成員函數指針。然後我想出了這個問題,並想知道這個解決方案實際上有多堅實。鑄造和語法是我的第一個紅旗,但是我認爲,由於它所擁有的數據的差異,這只是與領土一起出現。但我仍然不相信這是如何工作的。
*一個問題:*可能不適用於[指向虛擬成員函數的指針](http://coliru.stacked-crooked.com/a/4691b73521b8145e)。 'void *'不需要與任何*函數指針IIRC具有相同的大小。 – dyp
IIRC強制轉換函數指針無效,或者導致UB。 – RedX
@DyP:我剛剛檢查了虛擬成員函數,它確實有效。我會發布一些我以前用來證明的代碼。不過謝謝你! –