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++
Antwort
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;
}
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 –
@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. –
Können Sie uns zeigen, a [MCVE] Code, der dieses Problem zeigt? – Logicrat