-1

Nehmen wir an, Sie haben eine Klassenbasis und eine Klasse A, die von der Basis erbt. base hat eine Deklaration von reinen virtuellen Funktionen namens getValue(), die öffentlich ist, und A enthält die Definition (Implementierung) der Funktionen, die als privat festgelegt sind. Beim Versuch, die Funktion getValue() von der Basis Referenz zu verwenden oder Zeiger (Basis &/Basis *) an einen A Objekt sie es zugreifen, obwohl es als privateWarum virtuelle Funktionen Zugangsbezeichner trotzen? C++

+0

Können Sie uns zeigen, a [MCVE] Code, der dieses Problem zeigt? – Logicrat

Antwort

2

erklärt ist, weil in C++, Virtualität und Zugang sind orthogonal Bedenken. Wenn der Compiler ein base* oder base& sieht und es getValue darauf aufrufen muss, ist es ausreichend, dass die Funktion in base zugänglich ist.

Die Tatsache, dass A sein (überschreiben) getValue als private erklärt, ist irrelevant. Wie könnte es schließlich relevant sein? Wenn base.getValue() oder base->getValue() aufgerufen wird, kennen Sie nicht wissen, dass Sie mit einem A befassen können. Das ist der springende Punkt der objektorientierten Programmierung!


Dies bedeutet nicht, dass es zwar innerhalb einer Klassenhierarchie, Zugriffsbezeichner zu variieren guten Stil ist, weil es verwirrend sein kann. In der Tat sollten Sie Ihre getValue in zwei verschiedene Funktionen aufteilen, eine virtuelle und die andere nicht virtuelle.

Lange Geschichte: C++ verhält sich hier sehr anders als andere populäre Programmiersprachen, weil es tatsächlich ermöglicht und fördert private virtuelle Funktionen. Virtuelle Memberfunktionen sollten standardmäßig privat sein und öffentliche Memberfunktionen sollten standardmäßig nicht virtuell sein und bei Bedarf die privaten virtuellen Funktionen aufrufen. (Die einzige Ausnahme ist natürlich der Destruktor.) Herb Sutter nannte dies einmal die Non-Virtual Interface Idiom.

Beispiel:

#include <iostream> 

class Base 
{ 
public: 
    virtual ~Base() {} 

    int getValue() const 
    { 
     int const value = doGetValue(); 
     if (value < 0) 
     { 
      // error 
     } 
     return value; 
    } 

private: 
    virtual int doGetValue() const = 0; 
}; 

class A : public Base 
{ 
private: 
    int doGetValue() const override 
    { 
     return 123; 
    } 
}; 

int main() 
{ 
    Base* ptr = new A; // use std::unique_ptr in real code 
    std::cout << ptr->getValue() << "\n"; 
    delete ptr; 
} 
+0

Danke für die Antwort, aber ich habe ein wenig Mühe, diese zu verstehen: - Was ist std :: unique_ptr? -Warum create const Wert kann nicht direkt doGetValue() verwenden? -Warum muss ich 2 Funktionen eine virtuelle machen und die andere nicht? und danke im Voraus –

+0

@MekacherAnis Re: 'std :: unique_ptr': kann nicht im Kommentar erklären, bitte suchen Sie in Google. Re "warum const value": besserer Stil. Re: "Warum zwei Funktionen": Bitte lesen Sie den Artikel, den ich verlinkt habe. –