Trong khi chơi với việc triển khai toán tử gán ảo, tôi đã kết thúc bằng hành vi vui nhộn. Nó không phải là một trục trặc của trình biên dịch, vì g ++ 4.1, 4.3 và VS 2005 chia sẻ cùng một hành vi.Tại sao phân bổ ảo hoạt động khác với các chức năng ảo khác của cùng một chữ ký?
Về cơ bản, toán tử ảo = hoạt động khác với bất kỳ hàm ảo nào khác đối với mã thực sự đang được thực thi.
struct Base {
virtual Base& f(Base const &) {
std::cout << "Base::f(Base const &)" << std::endl;
return *this;
}
virtual Base& operator=(Base const &) {
std::cout << "Base::operator=(Base const &)" << std::endl;
return *this;
}
};
struct Derived : public Base {
virtual Base& f(Base const &) {
std::cout << "Derived::f(Base const &)" << std::endl;
return *this;
}
virtual Base& operator=(Base const &) {
std::cout << "Derived::operator=(Base const &)" << std::endl;
return *this;
}
};
int main() {
Derived a, b;
a.f(b); // [0] outputs: Derived::f(Base const &) (expected result)
a = b; // [1] outputs: Base::operator=(Base const &)
Base & ba = a;
Base & bb = b;
ba = bb; // [2] outputs: Derived::operator=(Base const &)
Derived & da = a;
Derived & db = b;
da = db; // [3] outputs: Base::operator=(Base const &)
ba = da; // [4] outputs: Derived::operator=(Base const &)
da = ba; // [5] outputs: Derived::operator=(Base const &)
}
Hiệu quả là các nhà điều hành ảo = có hành vi khác nhau hơn bất kỳ chức năng ảo khác với cùng một chữ ký ([0] so với [1]), bằng cách gọi phiên bản cơ sở của người điều khiển khi gọi qua Các đối tượng thực thụ ([1]) hoặc các tham chiếu có nguồn gốc ([3]) trong khi nó thực hiện như một hàm ảo thông thường khi được gọi thông qua các tham chiếu cơ sở ([2]), hoặc khi giá trị lvalue hoặc rvalue là tham chiếu cơ sở và giá trị khác Tham chiếu có nguồn gốc ([4], [5]).
Có giải thích hợp lý nào cho hành vi kỳ quặc này không?
Không có sự đoán mò nào liên quan ở đây. Các quy tắc rất nghiêm ngặt. – MSalters
Cảm ơn, Câu trả lời thực sự (như được đăng bởi ba người) là trình biên dịch tạo ra toán tử = cho lớp Derived ngầm gọi cho toán tử Base :: =. Tôi đánh dấu đây là 'câu trả lời được chấp nhận' vì đó là câu trả lời đầu tiên. –
'a = static_cast (b);' sẽ là một cách để tránh phôi kiểu C (mang theo nguy cơ vô tình làm một diễn viên diễn giải lại) –