Tôi muốn bind()
đến phiên bản lớp cơ sở của hàm của lớp từ lớp dẫn xuất. Chức năng được đánh dấu được bảo vệ trong cơ sở. Khi tôi làm như vậy, mã biên dịch vui vẻ trong Clang (Apple LLVM Compiler 4.1) nhưng đưa ra một lỗi trong cả g ++ 4.7.2 và trong Visual Studio 2010. Lỗi này nằm dọc theo dòng: "'Base :: foo': không thể truy cập thành viên được bảo vệ. "std :: bind() - ing một hàm thành viên được bảo vệ cơ sở từ hàm thành viên của lớp dẫn xuất
Ý nghĩa là ngữ cảnh cho tham chiếu thực sự nằm trong phạm vi bind()
, trong đó tất nhiên chức năng được xem là được bảo vệ. Nhưng không nên bind()
kế thừa ngữ cảnh của chức năng gọi - trong trường hợp này là Derived::foo()
- và do đó xem phương thức cơ sở là có thể truy cập?
Chương trình sau minh họa sự cố.
struct Base
{
protected: virtual void foo() {}
};
struct Derived : public Base
{
protected:
virtual void foo() override
{
Base::foo(); // Legal
auto fn = std::bind(&Derived::foo,
std::placeholders::_1); // Legal but unwanted.
fn(this);
auto fn2 = std::bind(&Base::foo,
std::placeholders::_1); // ILLEGAL in G++ 4.7.2 and VS2010.
fn2(this);
}
};
Tại sao có sự khác biệt về hành vi? Đó là chính xác? Giải pháp nào có sẵn cho các trình biên dịch lỗi?
Có chủ ý là 'Derived :: foo' tự gọi, hay chỉ là kết quả của việc đơn giản hóa một ví dụ? – aschepler
@aschepler Đó là phần "không mong muốn" của "hợp pháp nhưng không mong muốn". – OldPeculier