Statisk polymorfi
Undgå overhead fra virtuelle kald
Statisk polymorfi er en gratis C++ Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i C++ Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C++ Academy-kurset indeholder 4 lektioner i alt.
To former for polymorfi
C++ understøtter to former for polymorfi.
- Dynamisk: virtuelle funktioner afgøres ved kørsel via en virtuel tabel
- Statisk: skabeloner og CRTP afgøres ved kompilering
Statisk polymorfi bytter fleksibilitet for hastighed.
Omkostningen ved virtual
Et virtuelt kald kræver et indirekte spring gennem den virtuelle tabel. Kompileren kan normalt ikke indlejre det, hvilket forhindrer mange optimeringer.
#include <iostream>
struct Shape {
virtual double area() const = 0;
virtual ~Shape() = default;
};
struct Square : Shape {
double s;
Square(double x) : s(x) {}
double area() const override { return s * s; }
};
int main() {
Shape* p = new Square(3);
std::cout << p->area() << "\n";
delete p;
return 0;
}Statisk udvælgelse med CRTP
Med CRTP kalder basisklassen den afledte klasses metode direkte gennem en konvertering, der afgøres ved kompilering, så kompileren kan indlejre det hele.
#include <iostream>
template <typename T>
struct Shape {
double area() const { return static_cast<const T*>(this)->area(); }
};
struct Square : Shape<Square> {
double s;
Square(double x) : s(x) {}
double area() const { return s * s; }
};
int main() {
Square sq(3);
std::cout << sq.area() << "\n";
return 0;
}Navngivning af videresenderen
Når basisklassen og den afledte klasse begge definerer area, skal du give basisklassens videresender et særskilt navn som compute, så det entydigt kalder den afledte klasses implementering.
#include <iostream>
template <typename T>
struct Shape {
double compute() const { return static_cast<const T*>(this)->area(); }
};
struct Circle : Shape<Circle> {
double r;
Circle(double x) : r(x) {}
double area() const { return 3.14159 * r * r; }
};
int main() {
Circle c(2);
std::cout << c.compute() << "\n";
return 0;
}Skabeloner som statisk polymorfi
Almindelige funktionsskabeloner er også statisk polymorfi: Den samme kode fungerer for enhver type, der leverer den krævede grænseflade (såkaldt duck typing ved kompilering).
#include <iostream>
struct Dog { void speak() const { std::cout << "Woof\n"; } };
struct Cat { void speak() const { std::cout << "Meow\n"; } };
template <typename Animal>
void make_speak(const Animal& a) { a.speak(); }
int main() {
make_speak(Dog{});
make_speak(Cat{});
return 0;
}Når typen er kendt
Statisk polymorfi gælder kun, når den konkrete type er kendt ved kompilering. Hvis du skal gemme heterogene objekter i én beholder og vælge adfærd under kørsel, har du stadig brug for virtuelle funktioner.
Ingen heterogene beholdere
Du kan ikke placere Shape<Square> og Shape<Circle> i den samme std::vector som en fælles basisklasse, fordi de er ubeslægtede typer. Dette er den centrale begrænsning ved statisk polymorfi.
Ydelsesfordel
Ved at inline det kald, der afgøres ved dispatch, kan kompilatoren udføre konstantfoldning og helt eliminere overhead fra funktionskald. I tætte løkker over én kendt type kan statisk polymorfi være markant hurtigere.
#include <iostream>
template <typename T>
struct Op {
int apply(int x) const { return static_cast<const T*>(this)->apply(x); }
};
struct Doubler : Op<Doubler> {
int apply(int x) const { return x * 2; }
};
int main() {
Doubler d;
int sum = 0;
for (int i = 0; i < 5; ++i) sum += d.apply(i);
std::cout << sum << "\n";
return 0;
}Kombination af begge
Du kan bruge CRTP til den varme kodevej og et tyndt virtuelt omslag, når typeudviskning er nødvendig. Det giver hastighed dér, hvor det betyder noget, og fleksibilitet, hvor det er påkrævet.
Statiske grænsefladekontroller
Hvis en afledt klasse glemmer at implementere den krævede metode, vises fejlen ved kompilering, når basisvideresenderen instantieres, ikke under kørsel.
#include <iostream>
template <typename T>
struct Greeter {
void greet() const { static_cast<const T*>(this)->hello(); }
};
struct English : Greeter<English> {
void hello() const { std::cout << "Hello\n"; }
};
int main() {
English{}.greet();
return 0;
}Valg af det rette værktøj
Brug statisk polymorfi, når:
- Typen er kendt ved kompilering
- Ydeevnen er kritisk
- Du ikke har brug for en fælles basistype under kørsel
Ellers bør du foretrække virtuelle funktioner af hensyn til klarhed og fleksibilitet.
Hurtig kontrol
Vælg den vigtigste afvejning ved statisk polymorfi.
Opsummering
Du sammenlignede statisk og dynamisk polymorfi.
- Virtuelle funktioner = dispatch under kørsel, vtable, heterogene beholdere
- CRTP/skabeloner = dispatch ved kompilering, kan inline, hurtigere
- Statisk polymorfi kræver, at typen er kendt ved kompilering
- Vælg ud fra behovet for fleksibilitet kontra ydeevne
Lær C++ med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 51
- Lektioner
- 203
Ofte stillede spørgsmål
Er lektionen “Statisk polymorfi” gratis?
Ja — alle 3 lektioner i læringssporet C++ Academy, inklusive “Statisk polymorfi”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. C++ Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Statisk polymorfi”?
Undgå overhead fra virtuelle kald Du øver dig i C++ Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på C++ Academy?
Der kræves ingen tidligere erfaring. C++ Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Statisk polymorfi”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne C++ Academy-lektion?
Ja. Alle C++ Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- CRTP-idiomet
- Statisk polymorfi
- Mixins med CRTP
- Hvornår skal CRTP bruges