2014-09-20 11 views
7

Ich bin verwirrt über Überprüfung von Zugriffsbezeichner statisch oder dynamisch zu verstehen. Es wird gesagt, dass Zugriffsbezeichner nicht dynamisch überprüft werden. Was bedeutet das ?Sie möchten die Aussage „Barrierrefreiheit wird geprüft, statisch und nicht dynamisch in C++“

Dieses Beispiel wurde von verschiedenen posts auf SO genommen. Betrachten Sie dieses Beispiel

Beispiel A:

class Base 
{ 
public: 
    virtual void Message() = 0; 
}; 

class Intermediate : public Base 
{ 
    //Is Message method virtual here too ? is it private or public ? 
}; 

class Final : public Intermediate { 
    void Message() { 
     cout << "Hello World!" << endl; 
    } 
}; 

Final final; 

Jetzt nehme ich an so etwas wie dieses

Final* finalPtr = &final; 
finalPtr->Message(); 

die oben nicht funktionieren und mein Verständnis ist, dass die Nachricht Methode in Final Klasse ist privat. Ist das korrekt ? Wenn ja, warum funktioniert das? das Verfahren in

Intermediate* finalPtr = &final; // or Base* finalPtr = &final; 
    finalPtr->Message(); 

ist der Grund, warum der obige Code funktioniert, weil die Basisklasse Zeiger mit einer abgeleiteten Klasse instanziiert wird. Wenn ja, warum funktioniert der Aufruf von Message()? Der Post zu SO besagt, dass die Vererbung öffentlich ist und daher als öffentliche Funktion vererbt wird. Auf der anderen Seite hat die Funktion selbst in der Klasse den privaten Zugriffsspezifizierer (da standardmäßig ihr privater in einer Klasse ist). Ich bin hier verwirrt und ich würde mich freuen, wenn jemand das klären könnte. Wäre es richtig zu sagen, wenn eine Basisklasse mit einer abgeleiteten Klasse instanziiert wird. Dann hat der Zugriffsspezifizierer der Basisklassenmethode Vorrang vor dem Zugriffsspezifizierer der abgeleiteten Klasse?

Update:

Auch bemerkte ich, dass, wenn ich ändern, um die Intermediate und Final Code der folgenden

class Intermediate : public Base 
{ 
public: //Incase this public was absent then the following example wont work 
    void Message() { 
     cout << "Hello World! Intermediate" << endl; 
    } 
}; 

class Final : public Intermediate { 
    void Message() { 
     cout << "Hello World! final" << endl; 
    } 
}; 

und verwenden Sie es als solche

Intermediate* i = new Final(); 
    i->Message(); 

Dann inorder Holen Sie sich den Ausgang "Hello World! final" ist es notwendig, die Schnittstelle zu markieren Methode als öffentlich. Warum das ? Die Methode Message wurde als öffentlich vererbt. Warum muss ich es jetzt als öffentlich kennzeichnen?

+1

Sie sollten die anderen Beiträge verlinkt haben. Weil du es nicht getan hast, wirst du genau dieselbe Erklärung bekommen, die du nicht verstehst. –

+0

gerade hinzugefügt den Link – Rajeshwar

Antwort

8

Die Aussage in Ihrem Angebot bedeutet, dass die Zugriffsprüfung auf den statischen Typ des Ausdrucks basiert Sie den . Betreiber beantragt haben (oder ->, die * mit . entspricht).

Wenn T ist eine Art dann für:

T *t = something....; 
t->foo(); 

die die Zugriffsprüfung für den Namen ist T::foo, auch wenn der Zeiger verweist tatsächlich auf ein Objekt einer Klasse von foo abgeleitet.

Eine andere Möglichkeit, dies zu sagen ist, dass die Zugriffsprüfung zur Kompilierzeit durchgeführt werden muss. Es gibt keine "Run Time Accessability Failure".


In Ihrem Codebeispiel Sie haben:

Intermediate* finalPtr = something.....; 
finalPtr->Message(); 

Der Name ist Intermediate::Message nachgeschlagen werden. Die Klasse Intermediate hat Message als public Funktion, so dass diese Überprüfung erfolgreich ist.

Ihr Kommentar deutet darauf hin, dass Sie sich vielleicht nicht sicher sind, ob die vererbten Funktionen zugänglich sind. Es gibt drei Arten der Ableitung (etwas verwirrend, sie werden auch private, protected, public genannt). public Vererbung ist am häufigsten; Das bedeutet, dass public Mitglieder der Basisklasse auch public Mitglieder der abgeleiteten Klasse sind.

Da Base::Message ist öffentlich und Intermediate ist öffentlich von Base abgeleitet, dann Intermediate::Message ebenfalls öffentlich ist.

klar zu sein, ist es Namen die Zugriffsrechte haben. Base::Message und Intermediate::Message sind zwei verschiedene Namen, aber beide benennen die gleiche Funktion.

In Final, deklariert den Namen Message in seinem private Abschnitt, das bedeutet, dass Final::Message ist privat. Obwohl die Vererbung öffentlich war, überschattet die neue Deklaration eines Namens Final::Message den von der Basis ererbten Namen.


Um die "update" zu beantworten. Wenn der Code ist:

class Intermediate : public Base 
{ 
public: //Incase this public was absent then the following example wont work 
    void Message() { 
     cout << "Hello World! Intermediate" << endl; 
    } 
}; 

Sie haben Intermediate::Message als public deklariert. Daher können Sie die Funktion über einen Zeiger vom Typ Intermediate * aufrufen. Das ist was "öffentlich" bedeutet. Wenn Sie es private machen, dann können Sie es nicht anrufen.

Ich weiß nicht genau, was Sie meinen "Die Methode wurde als öffentlich vererbt. Warum muss ich sie jetzt als öffentlich markieren". Wenn Sie void Message() innerhalb class Intermediate schrieb, deklariert es eine neue Funktion. Der Name dieser Funktion überschattet den übernommenen Namen.

+0

Dann wäre es richtig zu sagen, wenn eine Basisklasse mit einer abgeleiteten Klasse instanziiert wird. Dann hat der Zugriffsspezifizierer der Basisklassenmethode Vorrang vor dem Zugriffsspezifizierer der abgeleiteten Klasse? – Rajeshwar

+0

Es gibt keine "Basisklasse wird mit einer abgeleiteten Klasse instanziiert", also wäre das nicht korrekt. –

+0

@Rajeshwar aktualisiert –

4

Diese Prüfung wird nur bei der Kompilierung durchgeführt.

Sie haben Message() öffentlich in Finale gemacht, so kann es aus endgültig bezeichnet werden.

Die Zwischenklasse hat keine Kenntnis davon, wie Nachricht in der Abschlussklasse definiert wird.

+0

Dann wird das korrekt sein? wenn eine Basisklasse mit einer abgeleiteten Klasse instanziiert wird. Dann hat der Zugriffsspezifizierer der Basisklassenmethode Vorrang vor dem Zugriffsspezifizierer der abgeleiteten Klasse? – Rajeshwar

+0

@Rajeshwar Wenn Sie einen Zeiger auf die Basisklasse haben, müssen Sie nur die Basisklasse Schnittstelle verwenden können, muss der Compiler keine Kenntnis von dem, was die Zeiger auf tatsächlich verweist. – molbdnilo

+0

Was?Er hat Message() privat in der Klasse Final gemacht, so dass er nicht über einen Verweis/Zeiger auf Final aufgerufen werden kann. Dies wird (statisch) zur Kompilierzeit überprüft, so dass die Funktion auch dann zur Verfügung bleibt, wenn zur Laufzeit der (dynamische) Typ des Objekts Final ist. –

1

Um Matt McNabbs Antwort kürzer zu machen. Wenn Sie den Zugriff der Funktion nicht angeben, ist sie privat. Wie Finale :: Nachricht

ist es für eine abgeleitete Klasse möglich, die Erreichbarkeit der Elternklasse herabzusetzen. Dies ist in einigen Fällen nützlich (wie das Blockieren von Standard-/Kopierkonstruktoren usw.)