Itu tidak mungkin, tapi itu hanya karena kelalaian. Itu bukan sesuatu yang "tidak masuk akal" karena banyak orang tampaknya mengklaim. Untuk lebih jelasnya, saya berbicara tentang sesuatu seperti ini:
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.
}
Ini adalah 100% sesuatu yang dapat diimplementasikan (hanya saja belum), dan saya berpendapat sesuatu yang berguna.
Pertimbangkan cara kerja fungsi virtual normal. Hapus static
s dan tambahkan beberapa hal lain dan kami punya:
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();
}
Ini berfungsi dengan baik dan pada dasarnya yang terjadi adalah kompiler membuat dua tabel, yang disebut VTables, dan memberikan indeks ke fungsi virtual seperti ini
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
};
Selanjutnya setiap kelas dengan fungsi virtual ditambah dengan bidang lain yang menunjuk ke VTable-nya, sehingga kompiler pada dasarnya mengubahnya menjadi seperti ini:
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";
}
};
Lalu apa yang sebenarnya terjadi ketika Anda menelepon b->sayMyName()
? Pada dasarnya ini:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(Parameter pertama menjadi this
.)
Oke, jadi bagaimana cara kerjanya dengan fungsi virtual statis? Nah apa perbedaan antara fungsi anggota statis dan non-statis? Satu-satunya perbedaan adalah bahwa yang terakhir mendapatkan this
pointer.
Kita dapat melakukan hal yang persis sama dengan fungsi virtual statis - cukup hapus this
pointer.
b->vtable[Base_Virtual_Functions::sayMyName]();
Ini kemudian dapat mendukung kedua sintaks:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
Jadi abaikan semua penentang. Ini tidak masuk akal. Mengapa itu tidak didukung? Saya pikir itu karena manfaatnya sangat kecil dan bahkan bisa sedikit membingungkan.
Satu-satunya keunggulan teknis atas fungsi virtual normal adalah Anda tidak perlu beralih this
ke fungsi tersebut, tetapi saya tidak berpikir itu akan membuat perbedaan yang terukur untuk kinerja.
Itu berarti Anda tidak memiliki fungsi statis dan non-statis yang terpisah untuk kasus ketika Anda memiliki instance, dan ketika Anda tidak memiliki instance, tetapi juga mungkin membingungkan bahwa itu hanya benar-benar "virtual" ketika Anda menggunakan panggilan instan.
const
dalam metode tanda tangan menandaithis
pointer implisit sebagai konstan dan tidak dapat diterapkan pada metode statis karena mereka tidak memiliki parameter implisit.