Video: C++ Tutorial #18 - Abstraktheit und Interfaces 2024
C ++ stöder sen bindning , som är när det löser ett metodanrop baserat på körtiden typ (eller dynamisk typ) av målobjektet snarare än den angivna typen (eller statisk typ). Detta visas i följande C ++ kodbit:
#include using namespace std; klassugn {public: virtual void cook () {cout << "matlagning med en ugn" << endl;}}; klass MicrowaveOven: public Oven {public: virtual void cook () {cout << "matlagning med mikrovågsugn" << endl;}}; void preparationMeal (Ugn och ugn) {ugn. cook ();}
I funktionen prepareMeal (), anropet till ugnen. kocken () kan passera till ugn:: cook () eller microwaveOven:: cook () beroende på körtid (typ "aktuell") av ugnsobjektet som passerat.
Det virtuella sökordet är kritiskt här. Utan den skulle koden () -metoden vara bunden tidigt, baserat på kompileringstidstypen, och anropa ugnen:: cook () varje gång. En gång förklarad virtuell i ugnsklassen antas metoden vara virtuell i varje underklass, men det gör inte ont för att upprepa deklarationen så att läsarna förstår.
Följande enkla program visar denna princip i praktiken:
int main () {Ugn; prepareMeal (ugn); MicrowaveOven mo; prepareMeal (mo); returnera 0;}
I detta program genererar anropet för att laga mata () två olika utgångar beroende på typ av ugn:
Matlagning med ugn Matlagning med mikrovågsugn
Det är inte alltid fallet, att en metod i basklassen kan definieras. Tänk på ugnsfallet noga. Det finns ett antal olika typer av ugnar - konventionella ugnar, konvektionsugnar och mikrovågsugnar - men man kan hävda att det inte finns någon riktig ugn som inte hör till någon av dessa underklasser. Du kanske kan säga hur olika typer av ugnar utför kockoperationen - det vill säga, vilken konventionalOven:: cook () och en MicrowaveOven:: cook () ska göra kan definieras. Det är förmodligen inte möjligt att definiera vilka åtgärder Oven:: cook () ska utföra.
Du kan inte helt enkelt lämna ugn:: cook () svart i ett starkt skrivet språk som C ++. Du kan dock förklara en metod men lämna den otillräcklig om det inte finns någon implementering. Man använder följande nyfikna syntax för att göra det:
klassugn {public: virtual void cook () = 0;};
Denna kod förklarar en metod Ovnen:: cook () som är bunden sen men genomför inte metoden. Faktum är att det går vidare genom att säga att metoden inte kommer att genomföras. I C ++ sägs en sådan metod vara ren virtuell . C ++ -programmerare använder också termen som föredras i många andra starkt skrivna datorspråk: abstrakt .Ugnsklassen sägs vara abstrakt.
En abstrakt representerar en egenskap som du vet att klassen har men vet inte hur man implementerar entydigt i den nuvarande klassen.
En klass är abstrakt om den innehåller en eller flera rena virtuella metoder. Betydelsen av detta är att du inte kan instansera en abstrakt klass. Således är följande inte längre tillåtet:
int main () {Ovnen; prepareMeal (ugn); returnera 0;}
Anledningen till detta är ganska enkelt: om du skapade ett objekt av klassugn och försökte åka på ugnen. cook (), vad ska kompilatorn göra?
På en mer filosofisk nivå är det bra att säga att det finns en del vanliga begrepp som kallas ugn som beskriver konventionella ugnar och mikrovågsugnar och konvektionsugnar. Denna term Ovnen är ett vanligt koncept eftersom det binder upp likheterna i alla dessa underklasser. Men det finns ingen förekomst av en ugn som inte är en av Ovns underklasser.
En underklass av en abstrakt klass är själv abstrakt tills alla rena virtuella metoder har överträtts av icke-abstrakta (det vill säga konkreta ) versioner. Klassen MicrowaveOven i det föregående kodstycket är således inte abstrakt - även om ugnen var abstrakt - eftersom den överrätter cook () med sin egen konkreta version.
Observera att det inte är något fel på funktionen prepareMeal () definierad enligt följande:
void preparationMeal (Ugn och ugn) {ugn. kock ();}
Även om argumentet förklaras vara en ugn, kan det endast påkallas med någon underklass av ugn, t.ex. MicrowaveOven eller ConventionalOven, för vilken kock () definieras.