Để trả lời câu hỏi này đầy đủ, bạn cần hiểu rằng thuộc tính là virtual
áp dụng độc lập với chính hàm đó và các cuộc gọi được thực hiện cho chức năng đó. Có các chức năng ảo và phi ảo. Có các cuộc gọi ảo và không ảo đến các chức năng này.
Điều tương tự cũng đúng về thuộc tính là inline
. Có các hàm iniline và non-inline. Và có được inline và không được gọi cuộc gọi đến các chức năng này.
Các thuộc tính này - virtual
và inline
- khi được áp dụng cho chính hàm đó, không xung đột. Họ chỉ đơn giản là không có lý do và không có cơ hội xung đột. Điều duy nhất mà các thay đổi chỉ định cho chính hàm đó là sửa đổi Quy tắc Một Định nghĩa cho hàm đó: hàm có thể được định nghĩa trong nhiều đơn vị dịch (và nó phải được định nghĩa trong mọi đơn vị dịch mà nó được sử dụng). Điều duy nhất virtual
thay đổi chỉ định là lớp chứa hàm đó trở nên đa hình. Nó không có ảnh hưởng thực sự lên bản thân hàm.
Vì vậy, hoàn toàn không có vấn đề khi khai báo hàm virtual
và inline
cùng một lúc. Không có cơ sở cho cuộc xung đột nào cả. Nó hoàn toàn hợp pháp trong ngôn ngữ C++.
struct S {
virtual void foo();
};
inline void S::foo() // virtual inline function - OK, whatever
{
}
Tuy nhiên, khi mọi người hỏi câu hỏi này, họ thường không quan tâm đến các thuộc tính của hàm, mà là đặc điểm của các cuộc gọi được thực hiện cho hàm.
Tính năng định nghĩa của một cuộc gọi ảo là nó đã được giải quyết tại thời gian chạy, có nghĩa là nó nói chung là không thể nội tuyến các cuộc gọi ảo đúng:
S *s = new SomeType;
s->foo(); // virtual call, in general case cannot be inlined
Tuy nhiên, nếu một cuộc gọi là do bản thân không ảo (mặc dù nó đi vào một hàm ảo), nội tuyến không phải là một vấn đề gì cả:
S *s = new SomeType;
s->S::foo(); // non-virtual call to a virtual function, can easily be inlined
Tất nhiên, trong một số trường hợp một trình biên dịch tối ưu hóa có thể có thể tìm ra các mục tiêu của một cuộc gọi ảo tại thời gian biên dịch và nội tuyến ngay cả cuộc gọi ảo như vậy. Trong một số trường hợp nó rất dễ dàng:
S ss;
ss.foo(); // formally a virtual call, but in practice it can easily be inlined
Trong một số trường hợp nó là phức tạp hơn, nhưng vẫn có thể làm được:
S *s = new S;
s->foo(); // virtual call, but a clever compiler might be able
// to figure out that it can be inlined
Tôi không thấy một câu hỏi thực sự ở đây ... –
hi, những gì làm bạn nghĩa là? Tôi đã không giải quyết vấn đề rõ ràng? Tôi lấy làm tiếc vì điều đó. – skydoor
Các chức năng nội tuyến không bao giờ cần thiết, vì vậy sẽ rất khó để hiển thị cho bạn một nội tuyến ảo cần thiết. – zneak