2015-11-04 15 views
9

Khi biên dịch ví dụ sau đây trong MSVC, tôi nhận đượcHành vi của tên đủ điều kiện sử dụng thừa kế riêng

'Giao diện' không thể truy cập bởi vì sử dụng 'cơ sở' 'tư nhân' để kế thừa từ 'Giao diện'

trong dòng được đánh dấu bằng Error. Khi cuộc gọi đến foo đủ điều kiện với bí danh loại cùng loại, nó hoạt động. Tôi đã thử nghiệm với msvc và ideone.

Tại sao hai cuộc gọi không bằng nhau?

struct Interface {}; 

template<class T> 
struct Base : private T 
{ 
    void foo() {} 
}; 

using BaseX = Base<Interface>; 

class Derived : Base<Interface> 
{ 
    Derived() { 
     Base<Interface>::foo(); // Error 
     BaseX::foo();    // Works 
    } 
}; 

Ideone

+0

Trông giống như lỗi msvc –

+0

@ DieterLücking, tôi đã thử sử dụng g ++ 4.9.3 và 'BaseX :: foo();' hoạt động. –

Trả lời

5

Tiêm-đẳng cấp tên.

Tên Interface được tiêm vào phạm vi của lớp Interface như thể đó là thành viên công khai và được kế thừa bởi Base<Interface> (với tư cách thành viên riêng vì bạn đang sử dụng kế thừa riêng).

Khi bạn viết Base<Interface>::foo() trong Derived, tra cứu tên không đủ tiêu chuẩn cho Interface trông đầu tiên tại Derived và lớp cơ sở của nó, thấy Interface trong lớp cơ sở, và sau đó truy cập vào đá kiểm soát trong vì tên đó là private.

Sửa chữa đơn giản nhất là chỉ viết Base::foo() hoặc thậm chí chỉ foo() nếu không phải là ảo và bạn không định viết foo() trong Derived.

Nếu bạn phải bao gồm đối số mẫu vì lý do nào đó, hãy viết Base<::Interface>.

+1

Tại sao chúng ta lại tìm kiếm 'Giao diện'? – Barry

+0

@Barry Um, bạn đã viết 'Base :: foo(); '... không chắc tại sao bạn nghĩ nó sẽ không được tra cứu. –

+0

@Barry Vâng, trước khi chúng tôi tra cứu 'foo', chúng ta cần biết phạm vi cần tìm trong (hoặc,' Base 'là gì) ... vì vậy bạn tra cứu' Base' và 'Interface'. –

Các vấn đề liên quan