Điều đó là không thể, nhưng đó chỉ là một thiếu sót. Đó không phải là điều "không có ý nghĩa" như nhiều người dường như tuyên bố. Để rõ ràng, tôi đang nói về một cái gì đó như thế này:
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.
}
Đây là 100% một cái gì đó có thể được thực hiện (nó chỉ không có) và tôi tranh luận một cái gì đó hữu ích.
Xem xét cách các chức năng ảo bình thường hoạt động. Xóa static
s và thêm vào một số thứ khác và chúng tôi có:
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();
}
Điều này hoạt động tốt và về cơ bản những gì xảy ra là trình biên dịch tạo hai bảng, được gọi là VTables và gán các chỉ mục cho các hàm ảo như thế này
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
};
Tiếp theo mỗi lớp với các hàm ảo được tăng cường với một trường khác trỏ đến VTable của nó, vì vậy trình biên dịch về cơ bản thay đổi chúng thành như sau:
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";
}
};
Sau đó, những gì thực sự xảy ra khi bạn gọi b->sayMyName()
? Về cơ bản này:
b->vtable[Base_Virtual_Functions::sayMyName](b);
(Tham số đầu tiên trở thành this
.)
Được rồi, vậy nó sẽ hoạt động như thế nào với các hàm ảo tĩnh? Vâng, sự khác biệt giữa các chức năng thành viên tĩnh và không tĩnh là gì? Sự khác biệt duy nhất là cái sau có được một this
con trỏ.
Chúng ta có thể làm chính xác như vậy với các hàm ảo tĩnh - chỉ cần loại bỏ this
con trỏ.
b->vtable[Base_Virtual_Functions::sayMyName]();
Điều này sau đó có thể hỗ trợ cả hai cú pháp:
b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".
Vì vậy, bỏ qua tất cả những người không tán thành. Nó có ý nghĩa. Tại sao nó không được hỗ trợ? Tôi nghĩ rằng bởi vì nó có rất ít lợi ích và thậm chí có thể hơi khó hiểu.
Lợi thế kỹ thuật duy nhất so với một chức năng ảo thông thường là bạn không cần phải chuyển this
sang chức năng đó nhưng tôi không nghĩ rằng điều đó sẽ tạo ra bất kỳ sự khác biệt có thể đo lường nào đối với hiệu suất.
Điều đó có nghĩa là bạn không có chức năng tĩnh và không tĩnh riêng cho các trường hợp khi bạn có một cá thể và khi bạn không có một cá thể, nhưng cũng có thể nhầm lẫn rằng nó chỉ thực sự "ảo" khi bạn sử dụng cuộc gọi ví dụ.
const
trong một chữ ký phương thức đánh dấuthis
con trỏ ẩn là hằng số và không thể được áp dụng cho các phương thức tĩnh vì chúng thiếu tham số ẩn.