2016-11-29 113 views
7

在C++ 11中,可以通過using聲明使外部(公共)成員可以訪問私有基類的公共成員。例如爲朋友功能使用聲明

class A { 
private: 
    int i = 2; 
public: 
    void f() { i = 3; } 

    friend bool operator==(const A& l, const A& r) { return l.i == r.i; } 
}; 

class B : private A { 
public: 
    using A::f; 
}; 

int main() { 
    B b, b2; 
    b.f(); 
} 

b.f()是可能的,因爲在B定義的using A::f的。

是否可以寫一個類似的聲明這將使得從B&向上投地A&可能的友元函數operator==(A&, A&),使b == b2可以main()被稱爲?

+4

你希望它可以上溯造型'B'爲'A'帶來什麼影響?那爲什麼要使用私有繼承?或者你只是想'operator =='工作?那麼爲什麼不直接聲明另一個'operator =='呢? – aschepler

+1

應該指出,朋友功能不是該類的成員,所以不應使用術語「upcast」。 – Goodies

回答

4

沒有,只有B可以在內部自身轉換爲A,這否則是不可能的,因爲從客戶的角度來看B不是A而是A

即使你更換你的friend bool operator=有一個成員函數equals

class A { 
private: 
    int i = 2; 
public: 
    void f() { i = 3; } 

    bool equals(const A& r){return i == r.i;} 
}; 

class B : private A { 
public: 
    using A::f; 
    using A::equals; 
}; 

雖然這編譯,你永遠不能撥打b.equals(b2),因爲從調用者的角度(由於私有繼承),從B類型到A類型的隱式轉換是不可能的。

您需要提供自己的operator==或將您的繼承權更改爲publicprotected。這裏就是B聲明的例子自己的friend bool operator==

class B : private A { 
public: 
    using A::f; 
    friend bool operator==(const B& l, const B& r) 
    { 
     return (static_cast<A>(l) == static_cast<A>(r)) && true; 
     // "true" is a stand-in for some other condition 
    } 
}; 

更多的isocpp


編輯: 如果你真的要玩遊戲,你會發現,我說沒有轉換有可能,但有些顯式轉換。由於B並專門從A派生你可以做指針鑄造,使其工作,但我不建議這樣做:

class A { 
private: 
    int i = 2; 
public: 
    void f() { i = 3; } 

    bool equals(const A* r){return i == r->i;} 
}; 

class B : private A { 
public: 
    using A::f; 
    using A::equals; 
}; 

int main() { 
    B b, b2; 
    b.f(); 
    (::A*)(&b)->equals((::A*)(&b2)); 
} 

或者你可以使用指針鑄造的醜表妹,參考鑄造,如果你想保留原來operator==語法

class A { 
private: 
    int i = 2; 
public: 
    void f() { i = 3; } 

    friend bool operator==(const A& l, const A& r) { return l.i == r.i; } 
}; 

class B : private A { 
public: 
    using A::f; 
}; 

int main() { 
    B b, b2; 
    b.f(); 
    ((::A&)(b)) == ((::A&)(b2)); 
} 

見§11.2[class.access.base]更多