Es ist nicht möglich, aber das liegt nur an einer Auslassung. Es ist nicht etwas, das "keinen Sinn ergibt", wie viele Leute zu behaupten scheinen. Um es klar zu sagen, ich spreche von so etwas:
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.
}
Das ist 100% etwas , das könnte umgesetzt werden (es hat einfach nicht), und ich würde etwas argumentieren , das nützlich ist.
Überlegen Sie, wie normale virtuelle Funktionen funktionieren. Entfernen Sie das static
s und fügen Sie einige andere Sachen hinzu und wir haben:
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();
}
Dies funktioniert einwandfrei. Im Grunde genommen erstellt der Compiler zwei Tabellen, die als VTables bezeichnet werden, und weist den virtuellen Funktionen wie diesen Indizes zu
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
};
Als nächstes wird jede Klasse mit virtuellen Funktionen um ein anderes Feld erweitert, das auf ihre VTable verweist, sodass der Compiler sie grundsätzlich so ändert:
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";
}
};
Was passiert dann eigentlich, wenn Sie anrufen b->sayMyName()
? Grundsätzlich ist dies:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(Der erste Parameter wird this
.)
Ok, gut, wie würde es mit statischen virtuellen Funktionen funktionieren? Was ist der Unterschied zwischen statischen und nicht statischen Elementfunktionen? Der einzige Unterschied besteht darin, dass letztere einen this
Zeiger erhalten.
Mit statischen virtuellen Funktionen können wir genau das Gleiche tun - entfernen Sie einfach den this
Zeiger.
b->vtable[Base_Virtual_Functions::sayMyName]();
Dies könnte dann beide Syntaxen unterstützen:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
Also ignoriere alle Neinsager. Es macht Sinn. Warum wird es dann nicht unterstützt? Ich denke, das liegt daran, dass es nur sehr wenig Nutzen hat und sogar etwas verwirrend sein kann.
Der einzige technische Vorteil gegenüber einer normalen virtuellen Funktion besteht darin, dass Sie nicht this
an die Funktion übergeben müssen, aber ich denke nicht, dass dies einen messbaren Unterschied für die Leistung bedeuten würde.
Es bedeutet, dass Sie keine separate statische und nicht statische Funktion für Fälle haben, in denen Sie eine Instanz haben und wenn Sie keine Instanz haben, aber es kann auch verwirrend sein, dass es nur wirklich "virtuell" ist, wenn Sie es verwenden der Instanzaufruf.
const
Signatur in einer Methode den implizitenthis
Zeiger als konstant und kann nicht auf statische Methoden angewendet werden, da ihnen der implizite Parameter fehlt.