我有關於成員指針的問題。下面的代碼無法同時使用的Oracle Solaris Studio 12.2的的CC編譯和Cygwin GCC 4.3.4,但與微軟的Visual C++工程2010:指向基類成員的指針的類型
struct A {
int x;
};
struct B : public A {
};
template<typename T> class Bar {
public:
template<typename M> void foo(M T::*p);
};
int main(int, char *[]) {
Bar<B> bbar;
bbar.foo(&B::x);
return 0;
}
在旁邊的最後一行上述兩種編譯器無法找到匹配Bar<B>::foo(int A::*)
。我寫了一個簡單的測試,以確認該表達&B::x
的類型實際上int A::*
是:
// ...
static void foo(int A::*p) {
std::cout << "A" << std::endl;
}
static void foo(int B::*p) {
std::cout << "B" << std::endl;
}
int main(int, char *[]) {
foo(&B::x); // prints "A", even on MS VC++ 2010
return 0;
}
以下解決方法可與GCC(不與Oracle CC尚未測試過),但無法與VC++由於歧義:
template<typename T> class Bar {
public:
template<typename M> void foo(M T::*p);
template<typename M, typename _T_base> inline void foo(M _T_base::*p) {
foo(static_cast<M T::*>(p));
}
};
我的問題: 哪種行爲正確?顯然,VC++會從int A::*
到int B::*
隱式轉換以滿足對成員函數模板的調用,其他兩個編譯器是否不應該這樣做?
也對答案感興趣,因爲我自己也遇到了類似的問題。我的理解是,由於多重繼承,'&B :: x'被默默地轉換爲'&A :: x'的錯誤是錯誤的:'B'的實例可能包含幾個'A'的實例,因此'&B :: x (可能)不明確。 – Dummy00001 2010-10-04 22:33:16
從我刪除的答案:'static_cast < int B::* >(&B :: x)'也適用。 – Potatoswatter 2010-10-04 23:18:29
@ Dummy00001:我懷疑,如果存在多重繼承,編譯器將像所有其他基類成員分辨率一樣運行,並輸出錯誤,指出名稱不明確。如果編譯器能夠解析名稱(應該在這裏),那麼它應該毫不費力地解決它。 – 2010-10-04 23:19:17