Non è possibile, ma è solo perché un'omissione. Non è qualcosa che "non ha senso", come molti sostengono. Per essere chiari, sto parlando di qualcosa del genere:
struct Base {
static virtual void sayMyName() {
cout << "Base\n";
}
};
struct Derived : public Base {
static void sayMyName() override {
cout << "Derived\n";
}
};
void foo(Base *b) {
b->sayMyName();
Derived::sayMyName(); // Also would work.
}
Questo è al 100% qualcosa che potrebbe essere implementato (semplicemente non l'ha fatto), e direi qualcosa di utile.
Considera come funzionano le normali funzioni virtuali. Rimuovi la static
s e aggiungi alcune altre cose e abbiamo:
struct Base {
virtual void sayMyName() {
cout << "Base\n";
}
virtual void foo() {
}
int somedata;
};
struct Derived : public Base {
void sayMyName() override {
cout << "Derived\n";
}
};
void foo(Base *b) {
b->sayMyName();
}
Funziona bene e in pratica ciò che accade è che il compilatore crea due tabelle, chiamate VTables, e assegna indici alle funzioni virtuali come questa
enum Base_Virtual_Functions {
sayMyName = 0;
foo = 1;
};
using VTable = void*[];
const VTable Base_VTable = {
&Base::sayMyName,
&Base::foo
};
const VTable Derived_VTable = {
&Derived::sayMyName,
&Base::foo
};
Successivamente ogni classe con funzioni virtuali viene aumentata con un altro campo che punta al suo VTable, quindi il compilatore sostanzialmente li cambia in questo modo:
struct Base {
VTable* vtable;
virtual void sayMyName() {
cout << "Base\n";
}
virtual void foo() {
}
int somedata;
};
struct Derived : public Base {
VTable* vtable;
void sayMyName() override {
cout << "Derived\n";
}
};
Quindi cosa succede realmente quando chiami b->sayMyName()
? Fondamentalmente questo:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(Il primo parametro diventa this
.)
Ok bene, quindi come funzionerebbe con le funzioni virtuali statiche? Bene, qual è la differenza tra le funzioni membro statiche e non statiche? L'unica differenza è che quest'ultimo ottiene un this
puntatore.
Possiamo fare esattamente lo stesso con le funzioni virtuali statiche: basta rimuovere il this
puntatore.
b->vtable[Base_Virtual_Functions::sayMyName]();
Questo potrebbe quindi supportare entrambe le sintassi:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
Quindi ignora tutti gli oppositori. Si fa senso. Perché non è supportato allora? Penso che sia perché ha pochissimi benefici e potrebbe anche essere un po 'confuso.
L'unico vantaggio tecnico rispetto a una normale funzione virtuale è che non è necessario passare this
alla funzione, ma non credo che farebbe alcuna differenza misurabile per le prestazioni.
Significa che non hai una funzione statica e non statica separata per i casi in cui hai un'istanza e quando non hai un'istanza, ma potrebbe anche confondere il fatto che sia veramente "virtuale" solo quando usi la chiamata di istanza.
const
firma in un metodo contrassegna ilthis
puntatore implicito come costante e non può essere applicato ai metodi statici poiché mancano del parametro implicito.