2010-01-31 137 views
3

全部。我無法理解爲什麼下面的代碼需要投射才能工作。有人可以解釋它嗎?成員指針基類

class Base { 
}; 

class Derived : public Base { 
}; 

class Class { 
public: 
    Derived member; 
}; 

... 

Derived obj; 
Base *ptrObj = &obj; // ok, no cast needed 

Derived Class::* ptr = &Class::member; // ok 
Base Class::* ptr = &Class::member; // wrong, need cast, why? 
+0

我從來沒有見過這種語法;有人鏈接到我的意思,這是不可能的谷歌搜索這些東西 – 2010-01-31 17:35:29

+2

這是一個指向成員。 :-) – 2010-01-31 17:38:36

回答

4

因爲如果Base被允許(協),然後你可以做到這一點,這是一個禁忌:

Base Class::* ptr = &Class::member; 
Class obj; 
obj.*ptr = Base(); // <-- assigned a Base into a Derived field?! 

與此同時,指針到成員不能是逆變要麼,因爲否則的話,你可以做到這一點,這也是一個禁忌:

struct Class2 { 
    Base member; 
}; 

Derived Class2::* ptr2 = &Class2::member; 
Class2 obj2; 
obj2.member = Base(); 
Derived& d = obj2.*ptr2; // <-- assigned a Base into a Derived 

所以,指針到成員既不是協變,也不逆變,但不變的:類型必須完全匹配。

+0

這不是很有說服力。你可以使用普通指針派生基類派生(否則將不允許派生派生類指針指向基類指針),那麼爲什麼不使用成員指針呢? – interjay 2017-03-19 00:10:31

0

好吧,我明白你的觀點Chris,但你的第一個例子適用於普通的指針。爲什麼它不適用於成員指針呢?看下面的代碼。

Derived obj; 
Base *ptr = &obj; 

*ptr = Base(); // it's weird, but ok 

第二個例子甚至不會對普通指針工作,因爲向下轉換並非沒有投不允許的。所以我不認爲這應該是一個解釋。

+1

使用「添加評論」功能添加評論,或編輯您的問題,而不是發佈非答案。 – 2010-01-31 18:23:14

+0

這與他的第一個例子不一樣。你不能使用普通的指針說'Derived * obj = Base()',因爲'Base'不是'Derived'。如果'Derived'具有'someInt'而不在'Base'中,會發生什麼?那麼當'obj'是'Base'時,當'obj-> someInt'時會發生什麼? – 2010-02-02 17:22:07