Ce n'est pas possible, mais c'est juste parce qu'une omission. Ce n'est pas quelque chose qui «n'a aucun sens» comme beaucoup de gens semblent le prétendre. Pour être clair, je parle de quelque chose comme ça:
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.
}
C'est quelque chose qui pourrait être implémenté à 100% (ce n'est tout simplement pas le cas), et je dirais quelque chose d'utile.
Considérez le fonctionnement des fonctions virtuelles normales. Supprimez les static
s et ajoutez d'autres éléments et nous avons:
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();
}
Cela fonctionne très bien et ce qui se passe, c'est que le compilateur crée deux tables, appelées VTables, et attribue des indices aux fonctions virtuelles comme celle-ci
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
};
Ensuite, chaque classe avec des fonctions virtuelles est augmentée avec un autre champ qui pointe vers sa VTable, de sorte que le compilateur les change fondamentalement pour être comme ceci:
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";
}
};
Alors que se passe-t-il réellement lorsque vous appelez b->sayMyName()
? Fondamentalement ceci:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(Le premier paramètre devient this
.)
Ok, alors comment cela fonctionnerait-il avec des fonctions virtuelles statiques? Quelle est la différence entre les fonctions membres statiques et non statiques? La seule différence est que ces derniers reçoivent un this
pointeur.
Nous pouvons faire exactement la même chose avec les fonctions virtuelles statiques - il suffit de supprimer le this
pointeur.
b->vtable[Base_Virtual_Functions::sayMyName]();
Cela pourrait alors prendre en charge les deux syntaxes:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
Alors ignorez tous les opposants. Il ne du sens. Pourquoi n'est-il pas pris en charge alors? Je pense que c'est parce que cela a très peu d'avantages et pourrait même être un peu déroutant.
Le seul avantage technique par rapport à une fonction virtuelle normale est que vous n'avez pas besoin de passer this
à la fonction, mais je ne pense pas que cela ferait une différence mesurable sur les performances.
Cela signifie que vous n'avez pas de fonction statique et non statique distincte pour les cas où vous avez une instance, et lorsque vous n'avez pas d'instance, mais il peut également être déroutant que ce soit vraiment "virtuel" lorsque vous utilisez l'appel d'instance.
const
signature in a method marque lethis
pointeur implicite comme constant et ne peut pas être appliqué aux méthodes statiques car elles n'ont pas le paramètre implicite.