Här undersöker vi hur arvsmekanismen fungerar, i synnerhet virtuella funktioner. Både hur de fungerar och hur de implementeras.
Kanske ännu viktigare är att labben också demonstrerar fallgropar och svårigheter med en arvshierarki.
Gör basen så enkel som möjligt.
Försök att göra areaberäkninga så tydliga som bara möjligt i programkoden.
Om du får lust att skriva
double Circle::getArea() const{
return 3.14 * std::pow(r, 2);
}
Bör du skämmas i lämplig utsträckning. Denna lilla snutt innehåller åtminståne två olämpligheter.
Om du får lust att i "shape.h" skriva
struct Circle: Shape{
Circle(double radius, std::string color = ""):Shapre(color), r(radius){}
double getArea() const override{ return /*nåt lämpligt*/; }
};
behöver du bara försvara det under redovisningen med -Det blev enklare så!
RoundedRectangle är en utmaning, du kommer sannolikt under redovisningen dessutom bli anklagad för att din RoundedRectangle beräknar arean fel[1]! Då gäller det att vara på tårna och vara extra tydlig i programkoden! Vi föredrar komposition framför både arv och sammansatta uttryck.
Innan redovisningen ser jag gärna att du undersökt en main.cpp
#include
struct S1{};
struct S2{
int i;
};
struct S3{
int i;
virtual void f(){}
};
int main(){
std::cout << sizeof S1() << '\n';
std::cout << sizeof S2() << '\n';
std::cout << sizeof S3() << '\n';
}
Jag ser gärna att du kan förklara alla tre storlekar. Den sista kan vara en smula invecklad men jag önskar att du åtminstone kan förklara varför den är större än S2.
Det inledande intrycket av arvshierarkin är för de flesta -Japp, det här känns rimligt!.
Om man däremot petar lite på grejerna börjar det skrynkla till sig rejält. Tänk på att ett arv beskriver både komposition och klassifikation. Det ger oss Liskows substitutionsprincip[2].
Redovisningen kommer att peka ut svagheterna med den föreslagna arvshierarkin.
[1]: Hur jag kan veta det på förhand avslöjas inte här.
[2]: What is an example of the Liskov Substitution Principle?