2016-11-29 3 views
7

In C++ 11 ist es möglich, ein öffentliches Mitglied einer privaten Basisklasse mit einer using Deklaration nach außen (öffentlich) zu machen. Zum Beispielusing-declaration für friend-Funktion

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() ist möglich, weil die using A::f in der Definition von B.

Ist es möglich, eine ähnliche Erklärung schreiben, die die oben Guss B&-A& möglich, dass der Freund Funktion operator==(A&, A&) machen würde, so dass b == b2 in main() genannt werden?

+4

Sie es möglich sein soll upCast 'B' auf 'A' im allgemeinen? Warum dann private Vererbung verwenden? Oder Sie wollen nur 'operator ==' arbeiten? Dann warum nicht einfach einen anderen 'operator ==' deklarieren? – aschepler

+1

Es sollte beachtet werden, dass die Friend-Funktion kein Mitglied der Klasse ist, daher sollte der Begriff "upcast" nicht verwendet werden. – Goodies

Antwort

4

Nein, nur B intern selbst zu A werfen können, und es ist sonst nicht möglich, da aus Sicht des Kunden B nicht ist einA sondern hat eineA

Auch wenn Sie Ihre friend bool operator= ersetzt mit einer Memberfunktion 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; 
}; 

Während diese kompiliert, können Sie nicht immer 012 anrufen, da keine implizite Konvertierung von einem Typ B zu einem Typ A aus der Sicht des Aufrufers (aufgrund privater Vererbung) möglich ist.

Sie müssen Ihre eigenen operator== oder ändern Sie Ihre Vererbung public oder protected. Hier ist ein Beispiel, wo B erklärt seine eigene 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 
    } 
}; 

Lesen Sie mehr bei isocpp


Edit: Wenn Sie wirklich Spiele spielen wollen, werden Sie feststellen, dass ich verneinte implizite Konvertierung immer möglich, aber einige explizite Konvertierungen sind. Da B nicht ableiten technisch von A Sie Zeiger Gießen tun können, damit es funktioniert, aber ich würde es nicht empfehlen:

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)); 
} 

Oder Sie könnten Zeiger Gießen hässliche Cousin, Referenz Gießen verwenden, wenn Sie das halten wollen Original operator== Syntax

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)); 
} 

Siehe §11.2 [class.access.base] für mehr

Verwandte Themen