2017-09-29 3 views
4

Ich habe eine einfache Frage in Bezug auf von einer Klasse erben, die privat von einer Basisklasse erben, das heißt, wir habenPrivat Erbe, Rückkehr Bezug auf statisches Element der Basisklasse

class Base {}; 
class Heir: private Base {}; 
class HeirsHeir : public Heir {}; 

In verstehen, dass HeirsHeir nichts von zugreifen kann 'seine' Basis. Insbesondere kann es keine Methode geben, die einen 'Base &'-Verweis auf sich selbst zurückgibt. Aber warum kann es nicht einen Verweis auf anderen Base-Objekt zurückgeben? Warum also der folgende Code nicht kompilieren:

class Base {}; 
class Kid : private Base {}; 
Base instance; 
class Grandkid : public Kid 
{ 
    const Base &GetInstance () const 
    { return instance; } 
}; 

Mindestens mein Compiler (MinGW 5.3, dh gcc für Windows) gibt

error 'class Base Base::Base' is inaccessible at {}; 
error: within this context const Base &getInstance() const 

Für mein Verständnis dieses macht keinen Sinn, da ich nicht tun Rufen Sie den Konstruktor von Base zu diesem Zeitpunkt auf, aber geben Sie eine Referenz (an eine Base-Instanz) zurück.

beachte, dass der Fehler kann durch Verwendung von

const ::Base &GetInstance () const 
{ return instance; } 

befestigt sein, die sicherlich zu C++ 03 verbunden ist §11.2/3 (siehe [C++ private inheritance and static members/types)

Hinweis: Ein Mitglied einer Die private Basisklasse ist möglicherweise nicht als geerbter Mitgliedsname verfügbar, aber direkt zugänglich.

Aber ich verstehe nicht, warum das notwendig ist. Kann es jemand erklären?

Dank

Chris

+0

aufgelöst wird Tut mir leid, dass ich von Base, Heir, HeirsHeir zu Parent, Kid, Grandkid und wieder zurück gewechselt habe ... –

Antwort

2

Der Name-Lookup findet den Namen der injizierten Klasse Base, der in Base injiziert wird (und somit von GrandKid geerbt wird). Dies ist richtig, da der Name der injected-Klasse in einem engeren Bereich liegt als der Name des Namensbereichs der Klasse. Dieser Name der Klasse injected ist jedoch nicht zugänglich für GrandKid, da es in Kid privat ist.

In der Fehlermeldung des Compilers bezieht sich Base::Base nicht auf den Konstruktor, sondern auf den Klassennamen Base, der in Base injiziert wird.Beachten Sie, dass, wenn der Kontext, in dem sie verwendet wird, den Namen als eine Art interpretiert werden zwingt, die Sie tatsächlich Base::Base legal nutzen können, wie in dieser gültig, aber vile Code:

class Foo {}; 

std::vector<Foo::Foo::Foo::Foo> v; 

[Live example]

Wenn jedoch der Kontext, in dem Base::Base verwendet wird, den Verweis auf eine Funktion zulässt, wird davon ausgegangen, dass der Konstruktor und nicht der Klassenname (C++ 11 [Klasse.qual] 3.4.3.1/2)

+0

Okay (ish), aber warum Klasse Base Base :: Base? –

+0

@ChrisN Frage GCC-Warnschreibmaschinen ;-) Aber ich denke, es bedeutet, dass "Klasse Base" der fragliche Typ ist und "Base :: Base" ist der Name, unter dem es gefunden wurde. – Angew

+0

Okay. Letzte Frage. Warum funktioniert auch die Klasse Base anstatt von :: Base (siehe JMA's Antwort)? Beschreibt das den Compiler, den globalen Bereich zu verwenden, oder ist das nur ein Nebeneffekt? Welcher der beiden wäre besser Stil? –

0

Ich denke, dass die compilter nicht Basis erkennt ist ein Klassenname, und erkennt sie als Sie ein Basiselement zugreifen möchten.

Dies kompiliert auch:

class Base {}; 
class Kid : private Base {}; 
Base instance; 
class Grandkid : public Kid 
{ 
    const class Base &GetInstance () const 
    { return instance; } 
}; 

Die falsche Verwendung Verwendung so etwas wie dieses würde:

class Base { 
public: 
    struct BaseStruct { int a; }; 
}; 
class Kid : private Base { 
public: 
    struct KidStruct { int a; }; 
}; 
Base instance; 
class Grandkid : public Kid 
{ 
    const class Base &GetInstance () const 
    { return instance; } 

    const Kid::KidStruct kidStruct; 
    const Base::BaseStruct baseStruct; 
}; 

kidStruct hat keine Fehler, weil Erbe öffentlich ist, aber baseStruct ist unzugänglich.

+0

Haben Sie eine Idee, wie diese Zeile geparst wurde? Welche Bedeutung hätte der Compiler in dieser Aussage zu "Base" geben können? – patatahooligan

+0

Okay, jetzt bin ich verwirrt. Warum versteht es nicht, dass es Klasse ist? Ich kann (etwas) verstehen, dass es nicht auf die Definition der Klasse zugreifen kann (die dann alle Methoden beinhaltet), aber was hilft es dann zu erklären "Hey, das ist eine Klasse"? –

+0

Es wird tatsächlich zu dem Klassennamen aufgelöst, aber zu dem injizierten (und unzugänglichen). – Angew

Verwandte Themen