It s not possible, but that s just because an omission. It isn t something that "doesn t make sense" as a lot of people seem to claim. To be clear, I m talking about something like this:
struct Base {
static virtual void sayMyName() {
cout << "Base
";
}
};
struct Derived : public Base {
static void sayMyName() override {
cout << "Derived
";
}
};
void foo(Base *b) {
b->sayMyName();
Derived::sayMyName(); // Also would work.
}
This is 100% something that could be implemented (it just hasn t), and I d argue something that is useful.
Consider how normal virtual functions work. Remove the static
s and add in some other stuff and we have:
struct Base {
virtual void sayMyName() {
cout << "Base
";
}
virtual void foo() {
}
int somedata;
};
struct Derived : public Base {
void sayMyName() override {
cout << "Derived
";
}
};
void foo(Base *b) {
b->sayMyName();
}
This works fine and basically what happens is the compiler makes two tables, called VTables, and assigns indices to the virtual functions like this
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
};
Next each class with virtual functions is augmented with another field that points to its VTable, so the compiler basically changes them to be like this:
struct Base {
VTable* vtable;
virtual void sayMyName() {
cout << "Base
";
}
virtual void foo() {
}
int somedata;
};
struct Derived : public Base {
VTable* vtable;
void sayMyName() override {
cout << "Derived
";
}
};
Then what actually happens when you call b->sayMyName()
? Basically this:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(The first parameter becomes this
.)
Ok fine, so how would it work with static virtual functions? Well what s the difference between static and non-static member functions? The only difference is that the latter get a this
pointer.
We can do exactly the same with static virtual functions - just remove the this
pointer.
b->vtable[Base_Virtual_Functions::sayMyName]();
This could then support both syntaxes:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
So ignore all the naysayers. It does make sense. Why isn t it supported then? I think it s because it has very little benefit and could even be a little confusing.
The only technical advantage over a normal virtual function is that you don t need to pass this
to the function but I don t think that would make any measurable difference to performance.
It does mean you don t have a separate static and non-static function for cases when you have an instance, and when you don t have an instance, but also it might be confusing that it s only really "virtual" when you use the instance call.